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
,因此这可能是实现此目的的可移植方式。
我在 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.
我试过了
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
,因此这可能是实现此目的的可移植方式。