Hibernate REQUIRES_NEW 或 NESTED 不适用于 MariaDB InnoDB

Hibernate REQUIRES_NEW or NESTED not working with MariaDB InnoDB

我在 JBoss-EAP 7.2.6 中有一个可能很长的 运行 事务,我需要在其中分几步提交。

我了解 MariaDB 没有嵌套事务,而是链式事务。这是我对它应该如何工作的想法:

public class MyEntityManager implements IMyEntityManager {
    @PersistenceContext(unitName = "org.x.y.z")
    protected EntityManager em;

    @Transactional(timeout = 900) // 15 minutes
    public void doTransaction(MyEntity me) {
        // Spring has a misfeature that @Transactional only applies when called from the outside.
        // Calling through an external reference works around this shortcoming. :-(
        MyEntityManager self = this;

        self.persist(me);
        publish(me.id); // Pseudocode, my read-only client eagerly waiting for id.

        // Fill me with more data
        self.flush();
        // Fill me with more data
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    private void persist(MyEntity me) {
        em.persist(me);
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    private void flush() {
        em.flush();
    }
}

我试过 NESTED,并将驱动程序从 2.4.3 升级到 2.5.4 无济于事。

如何让这样的场景与 InnoDB 一起工作?我愿意自己发布一个低级别 COMMIT AND CHAIN,因为在@Spring/Hibernate.

中似乎没有 API 这样做

我试过了

em.createNativeQuery("COMMIT AND CHAIN").executeUpdate();

但这会导致

XAER_RMFAIL: The command cannot be executed when global transaction is in the  ACTIVE state

em.unwrap(Session.class).createSQLQuery("COMMIT AND CHAIN").executeUpdate();

导致

GenericJDBCException: could not execute statement

仅将 this 复制到 self(我在别处找到的)是不够的。它需要 self = applicationContext.getBean(IMyEntityManager.class)。然后 NESTED 抛出不受支持。而 REQUIRES_NEW 完成了一个完整的交易,之后 me 不再被管理。

我有 xa-datasources,XA 事务不与正常 commit 混合。在我切换到普通数据源后,em.createNativeQuery("COMMIT AND CHAIN").executeUpdate() 就像一个魅力。

顺便说一句。我在 Arjuna 的 C++ 源代码中发现了一个方法 chainTransaction,它似乎没有导出到 Java。但我发现它只是做了另一个 BEGIN,这似乎暗示了 COMMIT,因此这可能是实现此目的的可移植方式。