CDI交易管理:@Transactional如何运作?

时间:2014-06-04 11:13:34

标签: java-ee jpa transactions ejb cdi

在会话范围内有一个简单的CDI bean,注入了实体管理器:

@Named("myBean")
@SessionScoped
public class MyBean implements Serializable {
    private static final long serialVersionUID = 1L;

    @Inject
    EntityManager em;
   ...

    @Transactional
    private void testInsert() {
        long t = System.currentTimeMillis();

        for (int i=1; i<50000; i++) {  
            create(i);
        }
       System.out.println("Time: " + Long.toString(System.currentTimeMillis()-t));
    }

    private void create(int i) {
        Project p = new Project("Project " + i);
        em.persist(p);
    }
}

现在,当通过EL#{myBean.testInsert}调用函数时,有两件事似乎很奇怪:

1)将@Transactional-annotation移动到方法create(int)我得到:

  

javax.persistence.TransactionRequiredException:JBAS011469:   执行此操作需要事务处理(使用a   事务或扩展持久化上下文)

2)用@Transactional装饰testInsert(),函数立即返回,但JPA仍然在后台线程中更新数据库。该过程需要2分钟才能完成仅50000条记录的INSERT。在进程中关闭Java EE应用程序服务器时,后台进程会停止,因此 - 在我看来 - testInsert()不是事务性的。

我的一般误解是什么?如何正确管理交易?

1 个答案:

答案 0 :(得分:4)

@javax.transaction.Transactional是Java EE 7中引入的拦截器绑定.CDI为您的bean注入的代理将拦截带注释的方法调用以将它们包装在事务中。

拦截器不适用于私人方法 - 我认为这是你的例子的主要问题。