JPA 事务回滚失败并调用无状态 bean

标签 jpa transactions persistence rollback ejb-3.1

在 BMT 内部(使用 UserTransaction),我调用另一个无状态 EJB 上的方法。当我回滚此事务时,在 EJB 方法中创建的实体不会回滚。我使用 EJB 3.1 和 JPA 2.0。事务从方法 doTheTransaction() 开始:

@Stateless
@LocalBean
@TransactionManagement(TransactionManagementType.BEAN)
public class TaskExecutor {

    @Inject private SomeEntityFacade someEntityEJB;
    @Inject private RandomEJB randomEJB;
    @Resource private UserTransaction ut;

    @Asynchronous
    public Future<String> doTheTransaction () { // we start here

        try {
            SomeEntity someEntity = new SomeEntity();
            someEntityEJB.create(someEntity); // this entity is rolled back

            // call another EJB to create a SomeEntity, this entity is not rolled back
            randomEJB.createSomeEntity();

            // cause error for test
            int i = 5 / 0;

            ut.commit();
        } catch (java.lang.ArithmeticException e) {
            ut.rollback();
        }
    }
    // Omitted exceptions thrown by UserTransaction methods because they give no problems
}

RandomEJB:

@Stateless
@LocalBean
@TransactionManagement(TransactionManagementType.BEAN)
public class RandomEJB {

    @Inject private SomeEntityFacade someEntityEJB;

    public void createSomeEntity () {
        // same code to create entity as in TaskExecutor:
        SomeEntity someEntity = new SomeEntity();
        someEntityEJB.create(someEntity);
    }
}

为了完整起见,以下是 SomeEntity 的基本部分:

@Stateless
@LocalBean
public class SomeEntityFacade {

    @PersistenceContext(unitName = "com.mysite.PU")
    private EntityManager em;

    public void create (SomeEntity p_someEntity) {
        em.persist(p_someEntity);
    }

如果您有兴趣,这是我的 persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
    <persistence-unit name="com.mysite.PU" transaction-type="JTA">
    <jta-data-source>jdbc/myDatabase</jta-data-source>
    <properties></properties>
    </persistence-unit>
</persistence>

为什么在RandomEJB中创建的实体没有回滚,而直接在事务中创建的实体却可以回滚?

也许this post是相关的,但我真的不明白给出的答案。

编辑:发现错误:使用 @TransactionManagement(TransactionManagementType.BEAN) 注释 RandomEJB。我的理解是,BMT交易不是通过其他BMT注释方法传播的,而是创建一个新交易。该事务可能会成功,而初始事务可能会失败并回滚。我想你在使用 BMT/CMT 带注释的方法时需要小心。有人可以证实这一点吗?

最佳答案

正如您所说 - BMT bean 不会相互共享事务。

这意味着您无法重用在另一个 BMT 中显式启动的事务。 BMT 就像“我知道游戏的内容,我会自己管理事务”。

所以:

  • BMT -> BMT 将不共享交易
  • BMT -> CMT 将共享事务(CMT 将使用实际事务 - 它不关心它是容器启动的还是用户启动的 - 它只关心事务是否存在)。

关于JPA 事务回滚失败并调用无状态 bean,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8438254/

相关文章:

java - jpql(NamedQuery)子查询不适用于参数

java - Spring事务没有正确回滚

mysql REPEATABLE_READ 和尚未存在的行

java - 运行 Spring 集成测试时为 "org.springframework.dao.InvalidDataAccessApiUsageException: Multiple representations of the same"

用于返回特定字段的 Spring data JPA

java.lang.IllegalStateException : Unable to retrieve EntityManagerFactory for unitName HorizonPU with Arquillian 错误

mysql - 没有 START TRANSACTION 语句的回滚在 MySQL 存储过程中不起作用

android - 如何在 Android 应用程序中保存项目

code-generation - 哪些 .NET 框架允许您先创建业务实体,然后再创建数据库

java - JPA 似乎有效但没有返回结果