当前位置: 首页 > 面试题库 >

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

子车高超
2023-03-14
问题内容

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

我已经使用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

所以,请给我您的意见。

谢谢。


问题答案:

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

听起来对我来说还算不错。实际上,当我们谈到
声明式事务划分

时,诸如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规范的所有细节以及动态代理的异常处理,但是有些棘手的情况)。这种代码可以隐藏细微的错误,因此值得花些时间使其防弹。



 类似资料:
  • 本文向大家介绍浅谈Java代理(jdk静态代理、动态代理和cglib动态代理),包括了浅谈Java代理(jdk静态代理、动态代理和cglib动态代理)的使用技巧和注意事项,需要的朋友参考一下 一、代理是Java常用的设计模式,代理类通过调用被代理类的相关方法,并对相关方法进行增强。加入一些非业务性代码,比如事务、日志、报警发邮件等操作。 二、jdk静态代理 1、业务接口 2、业务实现类 3、代理类

  • 本文向大家介绍Java静态代理和动态代理总结,包括了Java静态代理和动态代理总结的使用技巧和注意事项,需要的朋友参考一下 静态代理 第一种实现(基于接口): 1》接口 2》目标类,至少实现一个接口 3》代理类(与目标类实现相同接口,从而保证功能一致) 3》测试 第二种实现(基于目标类): 1>目标类 2>代理类(通过继承目标类,保证功能一致) 3>测试 动态代理 动态代理的代理类是在程序运行期间

  • 本文向大家介绍Java动态代理静态代理实例分析,包括了Java动态代理静态代理实例分析的使用技巧和注意事项,需要的朋友参考一下 代理模式:为其他对象提供一种代理以控制某个对象的访问。用在:在某些情况下,一个客户不想或者不能直接访问另一个对象,而代理对象可以在客户端和目标对象之前起到中介的作用,代理对象还可以完成它附加的操作。 例子:就像房东、租客、中介的关系。中介(代理对象)为房东(真实对象)出租

  • Proxy 动态代理是 jfinal AOP 的底层实现机制。jfinal 4.0 版本新增了 com.jfinal.proxy 模块用于消除对 cglib/asm 的依赖来实现动态代理。 proxy 模块需要运行在 JDK 环境之下,如果需要运行在 JRE 之下,可以添加如下配置来支持: public void configConstant(Constants me) { // 4.6 之

  • 是的,我见过类似的问题,但没有一个答案能真正引导我找到解决方案。我没有在任何地方使用这个线程,同样的代码在另一个jhipster应用程序中也可以使用,所以我不明白为什么这个提升转换会导致Hibernate问题。 例外: JPA地产: 编辑-这解决了我的问题:

  • 本文向大家介绍java中动态代理的实现,包括了java中动态代理的实现的使用技巧和注意事项,需要的朋友参考一下 动态代理的实现 使用的模式:代理模式。 代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。类似租房的中介。 两种动态代理: (1)jdk动态代理,jdk动态代理是由Java内部的反射机制来实现的,目标类基于统一的接口(InvocationHandler) (2)cglib动