الفريق العربي للبرمجةأرشيف المنتديات · 2000 – 2023
نسخة أرشيفية للقراءة فقط — التسجيل والمشاركة مغلقان، والمحتوى محفوظ كما كان.

إستخدام ال Java Dynamic Proxy مع ال JPA

بدأه mhewedy في 6 أبريل 2010 · 24 رد · 2,133 مشاهدة · في JavaEE
مشاركة: واتساب X فيسبوك تيليجرام
#1 صاحب الموضوع

كنت أعمل على بعض المشاريع التي تتطلب مني عدم استخدام Application Server , و بما إني أخترت أن أستخدم JPA كان على أن أستخدمه في ال Standalone mode,,,

فكرت في طريقه تجعلني أزكز الشفره الخاصه بإدارة ال Transaction ,,, ووصلت لأن أستخدم ال Java Dynamic proxy لتساعدني,,,

فالغرض من هذا الموضوع هو أني أريد رأيكم في إستخدام هذه التقنيه

هذه هي الشفره لل Dynamic proxy

package com.forat.service;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import com.forat.service.exceptions.DAOException;

/**
 * Example of usage :
 * <pre>
 * OnlineFromService onfromService = 
 *            (OnlineFromService) DAOProxy.newInstance(new OnlineFormServiceImpl());
 *        try {
 *            Student s = new Student();
 *            s.setName("Mohammed");
 *            s.setNationalNumber("123456");
 *            onfromService.addStudent(s);    
 *        }catch (Exception ex) {
 *            System.out.println(ex.getMessage());
 *        }
 *</pre>
 * @author mohammed hewedy
 *
 */
public class DAOProxy implements InvocationHandler{

    private Object object;
    private Logger logger = Logger.getLogger(this.getClass().getSimpleName());

    private DAOProxy(Object object) {
        this.object = object;
    }

    public static Object newInstance(Object object) {
        return Proxy.newProxyInstance(object.getClass().getClassLoader(), 
                    object.getClass().getInterfaces(), new DAOProxy(object));
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        EntityManagerFactory emf = null;
        EntityManager em = null;
        EntityTransaction et = null;
        Object result = null;
        try {
            emf = Persistence.createEntityManagerFactory(Constants.UNIT_NAME);
            em = emf.createEntityManager();;
            Method entityManagerSetter = object.getClass().
                getDeclaredMethod(Constants.ENTITY_MANAGER_SETTER_METHOD, EntityManager.class);
            entityManagerSetter.invoke(object, em);
            et = em.getTransaction();
            et.begin();
            result = method.invoke(object, args);
            et.commit();
            return result;
        }catch (Exception ex) {
            et.rollback();
            Throwable cause = ex.getCause();
            logger.log(Level.SEVERE, cause.getMessage());
            if (cause instanceof DAOException)
                throw new DAOException(cause.getMessage(), cause);
            else
                throw new RuntimeException(cause.getMessage(), cause);
        }finally {
            em.close();
            emf.close();
        }
    }
}

للمزيد (باللغه الإنكليزيه : http://m-hewedy.blogspot.com/2010/04/using-dynamic-proxies-to-centralize-jpa.html )

1
#2

بيني وبينك أخ هويدي لم أعمل أصلاً على JPA

ما رأيك لو تعطينا فكرة عن الموضوع

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#3

لقد تعاملت مع الـ JPA مع دعم للمناقلات Transactions من دون Application Sever من قبل

لكني لم أفهم كافة الأجزاء المتعلقة بالبروكسي :D

ما فائدتها وما الهدف منها ؟!

#4

أخي علاء, إن شاء الله قريبا

(أمال فيه عصام , مش باين بقاله كام يوم كده)

أخي محمد ,

الهدف من هذا الProxy هو تقليل و تركيز الكود ليصبح :

 public void addStudent(Student student) {
        em.persist(student);
    }

بدلا من :

public void addStudent(Student student) {
    EntityManagerFactory emf = null;
    EntityManager em = null;
    EntityTransaction et = null;
    try {
        emf = Persistence.createEntityManagerFactory(Constants.UNIT_NAME);
        em = emf.createEntityManager();;
        et = em.getTransaction();
        et.begin();
        em.persist(student);
        et.commit();
    }catch (Exception ex) {
        et.rollback();
    }finally {
        em.close();
        emf.close();
    }
}

تم تعديل هذه المشاركة بواسطة {هويدي} في 7 أبريل 2010 في 17:40

#5

عصام :(

طلب إعفاؤه عن الإشراف

بالمناسبة كنت أعتقد أن JPA ملتصقة بـ EJB التصاقاً وثيقاً

لكن يبدو أني كنت مخطئ

تحياتي

تم تعديل هذه المشاركة بواسطة علاء الصالحي في 7 أبريل 2010 في 17:49

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#6

هل ترك المنتدي؟ لاجل مسمي ؟؟

#7
اقتباس
بالمناسبة كنت أعتقد أن JPA ملتصقة بـ EJB التصاقاً وثيقاً

لكن يبدو أني كنت مخطئ

قديما قبل الـ EJB 3.0

كان كذلك ،،

أما الآن ، أصبحت الـ JPA لها

Specification ... خاص بها

################################

لم أفهم الغرض من الـ Proxy هنا ،

تعاملت قبل ذلك مع الـ Persistence في الـ Standalone app

ولكن بدون الطريقة المذكورة فوق

مجرد تحديد بعض الـ configuration files الخاصة بالـ DBMS والـ Entities التي سنقوم بعمل لها persist

ثم بالتعامل مع الـ SessionFactory لإنشاء Session والتي بدورها المسئولة عن عمل persist للـ objects

بدلاً عن الـ EntityManager كما كنا نفعل في الـ EJB

صــفــر

#8
اقتباس
ثم بالتعامل مع الـ SessionFactory لإنشاء Session والتي بدورها المسئولة عن عمل persist للـ objects

كانت Hibernate صح مش JPA صح ؟؟

اقتباس
الهدف من هذا الProxy هو تقليل و تركيز الكود ليصبح :

public void addStudent(Student student) {
        em.persist(student);
    }

بدلا من :

public void addStudent(Student student) {
    EntityManagerFactory emf = null;
    EntityManager em = null;
    EntityTransaction et = null;
    try {
        emf = Persistence.createEntityManagerFactory(Constants.UNIT_NAME);
        em = emf.createEntityManager();;
        et = em.getTransaction();
        et.begin();
        em.persist(student);
        et.commit();
    }catch (Exception ex) {
        et.rollback();
    }finally {
        em.close();
        emf.close();
    }
}

#9

Oo

صح معك حق ،، كانت Native Hibernate

يبدو اني خلطت الامور

شكراً لك علي الموضوع :)

صــفــر

#10

شكراً جزيلاً على المعلومة الهامة !

كنت أظن أن البروكسي هو فقط ذلك المستخدم لفتح المواقع المحجوبة :ph34r:

ولم أعلم أنه نموذج تصميمي Design Pattern شهير !

اقتباس
كانت Hibernate صح مش JPA صح ؟؟

سؤال خاطئ

JPA -كما تعلم- مجرد مواصفات specification بينما تحقيقاتها Implementation متعددة مثل :(Hibernate / EclipseLink / TopLink/ OpenJPA ....)

تم تعديل هذه المشاركة بواسطة Speed_Of_Light في 8 أبريل 2010 في 19:28

#11
اقتباس
سؤال خاطئ

JPA -كما تعلم- مجرد مواصفات specification بينما تحقيقاتها Implementation متعددة مثل :(Hibernate / EclipseLink / TopLink/ OpenJPA ....)

:) , أنا أقصد معني السؤال حرفيا, فإن كنت تستخدم Hibernate فإنه ليس معناه أنك قد تكون تستخدمها من داخل ال JPA , أنا أري أنك إن كنت تستخدم JPA فإنك تستخدم JPA ليس Hibernate أو EclispeLink ...

ممكن يتم التنويه أنك تستخدم JPA بال EclipseLink implementation مثلا...

#12
اقتباس
أنا أري أنك إن كنت تستخدم JPA فإنك تستخدم JPA ليس Hibernate أو EclispeLink ...

:huh:

لايوجد JPA يمكن استخدامه من دون Implementation ! وهذا طبيعي فالـ JPA هي مجرد مواصفات لا يمكنك استخدامها لوحدها.

كل Implementation يمكن أن يكون لها إضافات extension عن المواصفات ولكن هذا لا يغير شيئ !

جرب احذف مكتبات الـ Implementation ولاحظ أنه الـ JPA لن يعمل لوحده (لا يوجد تحقيق له كجزءً من الـ JDK) !

#13
اقتباس
جرب احذف مكتبات الـ Implementation ولاحظ أنه الـ JPA لن يعمل لوحده (لا يوجد تحقيق له كجزءً من الـ JDK) !

أتفق معك تماما, فالحزمتان javax.persistence.* و javax.persistence.spi.* يحتويان على Interface فقط http://java.sun.com/javaee/5/docs/api/javax/persistence/package-summary.html

و بالتالي فلابد من توافر implementation لهما ,,,,

لكني أردت أن أقول, دعنا نسمي JPA لمن يعمل على المواصفات بصرف النظر عن ال implementation,

فقولي "أنت تعمل على Hibernate وليس JPA", معناه أنت تعمل على org.hibernate.Session و ليس javax.persistnece.EntityManager

وصلت الفكره ؟

#14

أول مرة أعرف أن Hibernate يحقق JPA جيد جيد

كنت أعتقد أني بحاجة إلى دراسة JPA

إذن ماهي الحزمة التي تستخدمها أخ هويدي؟

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#16
اقتباس
إذن ماهي الحزمة التي تستخدمها أخ هويدي؟

كنت أستخدم Hibernate (لأنه التحقيق الإفتراضي لل JPA داخل JBoss AS ), ولكنني إستخدمت EclipseLink لأنه التحقيق الإفتراضي لل JPA في Eclipse في حالة ال Standalone app

حقيقه, أظن أن ال Eclipselink يتعامل بذكاء أكثر في إجدي أهم الحالات الحرجه التي يتجاهلها Hibernate ...

#17

بالنسبة للخلط بين الـ Hibernate والـ JPA

فهي اسمها Native Hibernate ،، اذا كنا لا نقصد الـ JPA

صــفــر

#18
اقتباس

حقيقه, أظن أن ال Eclipselink يتعامل بذكاء أكثر في إجدي أهم الحالات الحرجه التي يتجاهلها Hibernate ...

ماهي هذه الحالة؟

تحياتي

حزمة المحرك الإصدارة 0.8

أي أحد يجد أني ظلمته فليراسلني

وبإذن الله لو كان له حق سيأخذه

728x90.png

#19

Lazy loading ,,, في Hibernate لابد من أن تستدعي داله على ال Proxy object ليقوم Hibernate بعمل initialization له,,

و هذا ليس الحال في EclipseLink,,

ولعلك تعرف يا أخي, هذه حاله حرجه جدا, وخاصه للمبتدئين أمثالي

#20

أخي الكريم،،

استخدام Dynamic Proxy لا ارى فيه اي علاقة في Transactions هو يستخدم لعمل interception بحيث ممكن تعمل شيء مشابه AOP . مثال لو اردت ان تطبع كل محتويات كل دالية ممكن تتنادى بحيث ما تكتب عملية الطباعة في كل دالة ممكن تستخدم AOP لعمل ذلك و حده من المكتبات الناجحة هي Aspectj . ايضا الطريقة التي استخدم تستخدم في IoC مثل Spring framework.

اذا كنت تبي تعمل كل دالة بحيث تكون Transactional فممكن تستخدم annotation بحيث تكتب على كل دالة انها transactional و هذا موجود في JPA

تحياتي

مطور برامج مفتوحة المصدر، فستوريا

Open Source Portals, ECM, ERP, BPM - Vstoria

http://www.vstoria.com

#21
humancompiler كتب:

أخي الكريم،،

استخدام Dynamic Proxy لا ارى فيه اي علاقة في Transactions هو يستخدم لعمل interception بحيث ممكن تعمل شيء مشابه AOP . مثال لو اردت ان تطبع كل محتويات كل دالية ممكن تتنادى بحيث ما تكتب عملية الطباعة في كل دالة ممكن تستخدم AOP لعمل ذلك و حده من المكتبات الناجحة هي Aspectj . ايضا الطريقة التي استخدم تستخدم في IoC مثل Spring framework.

نعم هو كذلك, أتفق معك مئه بالمئه, فأنها هنا لم أكن أريد أستخدم شئ سوي ال JDK , لا أريد تقدم مكتبات خارجيه سواء ل Aspectj أو Spring.

humancompiler كتب:

اذا كنت تبي تعمل كل دالة بحيث تكون Transactional فممكن تستخدم annotation بحيث تكتب على كل دالة انها transactional و هذا موجود في JPA

أختلف معك, فإدارة العمليات (Transaction management) , هي مهمه من مهام حاوي ال EJB , وليست مهمه من مهام ال JPA , ومن هنا أتت التسميه CMT (Container-Manage Trasactions)

فهذه ال Annotations توضع فوق دوال ال Session Beans.

شكرا,,,

#22
{هويدي} كتب:

نعم هو كذلك, أتفق معك مئه بالمئه, فأنها هنا لم أكن أريد أستخدم شئ سوي ال JDK , لا أريد تقدم مكتبات خارجيه سواء ل Aspectj أو Spring.

أختلف معك, فإدارة العمليات (Transaction management) , هي مهمه من مهام حاوي ال EJB , وليست مهمه من مهام ال JPA , ومن هنا أتت التسميه CMT (Container-Manage Trasactions)

فهذه ال Annotations توضع فوق دوال ال Session Beans.

شكرا,,,

هلا اخوي ،،

كما تعرف JPA ممكن تعمل مع EJB Container أو من دون. ممكن توضح ليش Transaction ليست من مهام JPA لأنه اصلا Transaction من مهام JTA و اغلب Application Servers تدعم JTA مثل Weblogic http://download.oracle.com/docs/cd/E13222_01/wls/docs81/jta/gstrx.html#1018509

JTA عبارة عن Interfaces تحدد التخاطب بين Resource Manager و Transaction Manager . طبعا ممكن عمل Transactions بدون JTA من خلال JDBC . و لو تقرأ JPA Specification هنا ستجد انها ايضا تستخدم JTA

http://cds-esd.sun.com/ESD24/JSCDL/ejb/3.0-fr/ejb-3_0-fr-spec-persistence.pdf?AuthParam=1271350224_fafffd5677b0a830487a312dffa86303&TicketId=B%2Fw4lRmATlpLSRFKOlNflwfr&GroupName=CDS&FilePath=/ESD24/JSCDL/ejb/3.0-fr/ejb-3_0-fr-spec-persistence.pdf&File=ejb-3_0-fr-spec-persistence.pdf

تقبل تحياتي

تم تعديل هذه المشاركة بواسطة humancompiler في 15 أبريل 2010 في 19:54

مطور برامج مفتوحة المصدر، فستوريا

Open Source Portals, ECM, ERP, BPM - Vstoria

http://www.vstoria.com

#23

لعلك أدري مني يا أخي,

معني ذلك هل يمكنني إستخدام CMT خارج ال EJB Container ؟؟ لا لا أعتقد

فأنا هنا أريد أن أستخدم JPA خارج ال Container ولذا أنا لا أستخدم ال CMT

اقتباس
اغلب Application Servers تدعم JTA مثل Weblogic

نعم ال App Server يدعم ال JTA كخاصيه تتكامل مع ال JPA وليست جزءا منها (هذا ما أعرفه, قد أبدوا مخطآ)

إذن, نحن لدينا نوعين من الTnxs , و هما CMT و BMT,

ال CMT يتطلب وجود Container , وهو الذي يقوم بإدارة ال Tnx بدلا منك

ال BMT لا يتطلب وجود Container , و يجب عليك إدارة ال Tnx بنفسك (و هذا هو حال المثال الذي لدينا, حيث أنني لم أريد أن أستخدم App Server )

#24

لا العفو اخي الكريم،، انا سعدت و تشرفت بنقاش معك. و أنا متأكد تمام الثقة اني لست بخبرتك الطويلة

تقبل تحياني اخي الكريم

مطور برامج مفتوحة المصدر، فستوريا

Open Source Portals, ECM, ERP, BPM - Vstoria

http://www.vstoria.com

#25

مرحبا بك أخي الكريم في منتداك,,,

وشكرا على هذا الإطراء الذي لا أستحقه يقيناً

مواضيع مشابهة