CDI 中@Transactional 的限制是什么?

fre*_*low 2 ejb jpa cdi jakarta-ee

我试图@Transactional在 CDI 类中使用一种方法,而不是 EJB:

@javax.inject.Named
// fails @javax.enterprise.context.ApplicationScoped
// fails @javax.enterprise.context.SessionScoped
// works @javax.ejb.Singleton
// works @javax.ejb.Stateless
public class SomeClass {
    @javax.persistence.PersistenceContext
    private EntityManager em;

    @javax.annotation.PostConstruct    
    @javax.transaction.Transactional
    public void someMethod() {
        em.persist(someEntity);
    }
}
Run Code Online (Sandbox Code Playgroud)

当我SomeClass@Singletonor注释时@Stateless,一切正常。

当我SomeClass@ApplicationScoped或注释时@SessionScoped,WildFly 13 显示以下错误消息:

执行此操作需要事务(使用事务或扩展持久性上下文)

我的印象是@Transactional从 Java EE 7 开始就可以使用 CDI。我是不是弄错了?或者我只是缺少一些额外的配置?

Nik*_*los 6

在尝试@Transactional使用 CDI进行工作时,我将尝试给出一个简短的清单,以便给出比评论更有价值的答案:

  1. 我们正在讨论javax.transaction.Transactional,而不是javax.ejb.TransactionAttribute,它适用于 EJB!
  2. 它不能在非 JEE 应用程序中开箱即用!
  3. JEE 应用程序是指那些运行完整 JEE 应用程序服务器的应用程序;开箱即用的 Tomcat 不支持它!
  4. 当心类路径问题,特别是确保javax.transaction.Transactional在完整的 JEE 应用程序服务器中运行时不存在包含注释的 jar,例如在 WEB-INF/lib 中。如果要在非完整 JEE 环境中使用它,则需要将它放在类路径中。
  5. @Transactional被最新的 JTA 规范作为 CDI 拦截器实现。像这样:
    • 它不在 JEE < 7 中!
    • 它具有与任何拦截器相同的限制。例如,它不能被初始化方法调用 - @PostConstruct[这是这个问题中的问题],并且在调用对象的方法时它不会被激活this,当心!!!
  6. 我很有信心可能存在更多错误!!!