استخدام الوكلاء الديناميكي لمركزية رمز JPA

StackOverflow https://stackoverflow.com/questions/2587702

  •  24-09-2019
  •  | 
  •  

سؤال

في الواقع ، هذا ليس سؤالًا ، لكنني في الحقيقة أحتاج إلى آرائك في مسألة ما ... أضع منشوره هنا لأنني أعلم أنك نشط دائمًا ، لذا من فضلك لا تعتبر هذا سؤالًا سيئًا ومشاركة آرائك.

لقد استخدمت الوكلاء الديناميكي Java لتركيز رمز JPA الذي استخدمته في وضع مستقل ، وإليك رمز الوكيل الديناميكي:

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)

لذا ، من فضلك أعطني آرائك.

شكرًا.

هل كانت مفيدة؟

المحلول

لذلك قمت بتغليف منطق ترسيم المعاملة في مكان واحد واستخدمت الوكيل الديناميكي لتعزيز الخدمات الحالية مع إدارة المعاملات وتقليل رمز الغلاية ، أليس كذلك؟

يبدو لي على ما يرام بالنسبة لي. في الواقع ما هي الحاويات مثل الربيع أو EJB عندما نتحدث عنه ترسيم المعاملة التصريح متشابه كثيرا. التنفيذ ، يمكنك القيام بذلك باستخدام وكيل ديناميكي ، أو أجهزة رمز البايت ، أو حتى استخدام SABNEJ. لقد فعلت شيئًا مشابهًا جدًا مرة واحدة لإطار اختبار صغير مرة واحدة. هنا مشاركة مدونة حوله.

الأجزاء الصعبة التي أراها هي:

1) التراجع فقط. وفقًا لمواصفات JPA ، يمكن وضع علامة على معاملة الكيان على أنها ""التراجع فقط". مثل هذه المعاملة لا يمكن أن تلتزم أبدًا. لذلك أشعر أنه يجب عليك التحقق من ذلك بين هذين الخطين:

result = method.invoke(object, args);
et.commit();

2) إعادة الدخول. معظم الأنظمة التي لديها معاملات إعلانية تنفذ دلالات تبدأ فيها المعاملة فقط إذا لم يكن هناك واحد نشط بالفعل (انظر "مطلوب" في هذه القائمة التعليقات التوضيحية EJB). يبدو أنك يجب أن تحقق مع isActive هذا في منطقك.

3) معالجة الاستثناء. كن حذرا للغاية مع استثناء الانتشار في الوكيل الديناميكي. من المفترض أن يكون الوكيل شفافًا للعميل قدر الإمكان. إذا كان استثناء غير DAOException يتسرب من Dao ، وسيقوم الوكيل بتحويله إلى أ RuntimeException. لا يبدو لي الأمثل. أيضا لا تخلط بين الاستثناء بسبب invoke فشلت ، والاستثناء ملفوف من قبل الاحتجاج ، وأعتقد أنه يجب عليك إعادة إدخال كما هو:

catch ( InvocationTargetException e )
{
     Throwable nested = e.getTargetException();
     throw nested;
}

خاتمة: فكرة استخدام الوكيل الديناميكي في هذا السيناريو تبدو جيدة بالنسبة لي. لكنني أظن أن هناك بعض الأشياء التي يمكنك التحقق منها في الكود (لا أتذكر كل تفاصيل مواصفات JPA والتعامل مع الاستثناء مع الوكيل الديناميكي ، ولكن هناك بعض الحالات الصعبة). يمكن لهذا النوع من التعليمات البرمجية إخفاء الأخطاء الدقيقة ، لذلك يجدر قضاء بعض الوقت لجعله مقاومًا للرصاص.

نصائح أخرى

لقد استخدمت شيئًا مشابهًا في الماضي ، لكن مشفرًا إلى واجهة برمجة تطبيقات السبات (كان هذا قبل JPA). تمت إدارة الوصول إلى البيانات لمعظم أنواع DAO من خلال واجهة سميت باسم نوع الكائن ، مثل CustomerPersistence لإدارة العملاء. طرق مثل FindXXX تم تعيينها إلى الاستعلامات المسماة ، مع أسماء المعلمات في الطريقة التي تم تعيينها للمعلمات في الاستعلام.

كان تنفيذ الواجهات وكلاء ، والذين استخدموا اسم الواجهة ، وأسماء الأسلوب ، وأسماء المعلمات ، إلخ. لاستدعاء الطرق المناسبة في واجهة برمجة تطبيقات Hibernate.

إنه يوفر الكثير من ترميز Boilerplate ، مع رسم خرائط بديهي لإطار الوصول إلى البيانات الأساسي ، ويجعل السخرية السهلة للغاية لطبقة الوصول إلى البيانات.

لذلك ، أنا بالتأكيد "إبهام" على استخدام الوكلاء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top