I have a potentially long-running transaction in JBoss-EAP 7.2.6 where I need to commit in several steps.
I understand that MariaDB has no nested, but chained transactions. This is my idea of how this should work:
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();
}
}
I tried going to NESTED
, and upgrading driver from 2.4.3 to 2.5.4 to no avail.
How to get such a scenario to work with InnoDB? I'd be willing to issue a low level COMMIT AND CHAIN
myself, as there seems to be no API for doing so in @Spring/Hibernate.
I tried
em.createNativeQuery("COMMIT AND CHAIN").executeUpdate();
but this leads to
XAER_RMFAIL: The command cannot be executed when global transaction is in the ACTIVE state
while
em.unwrap(Session.class).createSQLQuery("COMMIT AND CHAIN").executeUpdate();
leads to
GenericJDBCException: could not execute statement
Just copying this
to self
(which I'd found elsewhere) is not enough. It needs self = applicationContext.getBean(IMyEntityManager.class)
. Then NESTED
throws unsupported. Whereas REQUIRES_NEW
does a complete transaction, after which me
is no longer managed.
I have xa-datasources, and XA transactions don't mix with normal commit
. After I switched to a normal datasource, em.createNativeQuery("COMMIT AND CHAIN").executeUpdate()
works like a charm.
Btw. I found in the C++ source code of Arjuna a method chainTransaction
which doesn't seem to be exported to Java. But I found it just does another BEGIN
which seems to imply a COMMIT
, so that might be the portable way to achieve this.