0

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

1 Answer 1

0

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.