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

发布于 2024-12-20 07:40:15 字数 2738 浏览 2 评论 0原文

在 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 中创建实体没有回滚,而直接在事务内创建的实体是?

也许这篇文章相关,但我真的不明白给出的答案。

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

Inside a BMT (using a UserTransaction) I call a method on another stateless EJB. When I rollback this transaction, the entity created in the EJB method is not rolled back. I use EJB 3.1 with JPA 2.0. The transaction begins in method 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
}

The 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);
    }
}

To be complete, here is the essential part of SomeEntity:

@Stateless
@LocalBean
public class SomeEntityFacade {

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

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

If you are interested, this is my 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>

Why is the entity created in RandomEJB not rolled back, while the entity created directly inside the transaction is?

Maybe this post is related, but I really don't understand the answer given.

Edit: found the error: annotating RandomEJB with @TransactionManagement(TransactionManagementType.BEAN). My understanding is that BMT transactions are not propagated through other BMT annotated methods, instead a new transaction is created. That one can succeed while the initial transaction can fail and rollback. I guess you need to be carefull when using BMT/CMT annotated methods. Can someone confirm this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

不再见 2024-12-27 07:40:15

就像你说的那样 - BMT beans 不相互共享事务。

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

所以:

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

It's just like you said - BMT beans are not sharing the transaction with each other.

This means that you cannot reuse transaction you explicitly started in another BMT. BMT is like "I know what the game is about, I'll manage the transactional stuff myself".

So:

  • BMT -> BMT will not share transaction
  • BMT -> CMT will share transaction (CMT will use the actual transaction - it doesn't care if it's container started or user-started - it's just interested in fact that the transaction exist).
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文