【问题标题】:CDI Transaction Management: How does @Transactional work?CDI 事务管理:@Transactional 是如何工作的?
【发布时间】:2014-06-04 11:13:33
【问题描述】:

在会话范围内拥有一个简单的 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: 执行此操作需要事务(使用 事务或扩展持久性上下文)

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

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

【问题讨论】:

    标签: jakarta-ee jpa transactions ejb cdi


    【解决方案1】:

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

    拦截器不适用于私有方法 - 我想这是您的示例的主要问题。

    【讨论】:

    • 这里只是一个附带问题。是否有特定的方法来拦截容器管理的所有事务?对于我的应用程序,我需要在每个事务开始时注入自定义 SQL 查询。我找不到任何与此相关的文档。亲切的问候。
    猜你喜欢
    • 1970-01-01
    • 2012-12-19
    • 2015-05-31
    • 2018-09-15
    • 1970-01-01
    • 1970-01-01
    • 2017-02-24
    • 2014-11-30
    • 2014-10-31
    相关资源
    最近更新 更多