使用动态代理集中化JPA代码

实际上,这不是一个问题,但实际上我需要您的意见…我把他的帖子放在这里是因为我知道您一直都很活跃,所以请不要认为这是一个坏问题并与我分享您的意见。

我已经使用Java动态代理" title="动态代理">动态代理来集中化在独立模式下使用的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)

所以,请给我您的意见。

谢谢。

回答:

因此,您已经将事务划分逻辑封装在一个地方,并使用动态代理通过事务管理来增强现有服务并减少样板代码,对吗?

听起来对我来说还算不错。实际上,当我们谈到

时,诸如Spring或EJB之类的容器所做的事情非常相似。在实现方面,您可以使用动态代理或字节码检测来实现,甚至可以使用AspectJ。我曾经为一个很小的测试框架做过非常相似的事情。这是关于它的博客文章。

我看到的棘手的部分是:

1) 。根据JPA规范,实体事务可以标记为“

仅回滚

”。这样的交易永远无法提交。因此,我觉得您应该在这两行之间进行检查:

result = method.invoke(object, args);

et.commit();

2)

。大多数具有声明式事务的系统都实现一种语义,即只有在没有事务处于活动状态时才启动事务(请参阅此EJB批注列表中的“ Required” )。看来您应该isActive按照逻辑检查一下。

3) 。注意动态代理中的异常传播。代理应该对客户端尽可能透明。如果DAOExceptionDAO

以外的其他异常泄漏出去,则代理会将其转换为RuntimeException。对我来说听起来并不理想。同样不要混淆异常,因为invoke失败了,并且调用包装了异常,我认为您应该照原样重新抛出:

catch ( InvocationTargetException e )

{

Throwable nested = e.getTargetException();

throw nested;

}

:在这种情况下使用动态代理的想法对我来说是可以的。但是我怀疑您需要仔细检查代码中的一些内容(我不记得JPA规范的所有细节以及动态代理的异常处理,但是有些棘手的情况)。这种代码可以隐藏细微的错误,因此值得花些时间使其防弹。

以上是 使用动态代理集中化JPA代码 的全部内容, 来源链接: utcz.com/qa/404252.html

回到顶部