Hibernate REQUIRES_NEW или NESTED не работает с MariaDB InnoDB - PullRequest
0 голосов
/ 09 марта 2020

У меня есть потенциально длительная транзакция в 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

1 Ответ

0 голосов
/ 25 марта 2020

Простого копирования this в self (который я нашел в другом месте) недостаточно. Нужно self = applicationContext.getBean(IMyEntityManager.class). Затем NESTED выбрасывает без поддержки. Принимая во внимание, что REQUIRES_NEW выполняет полную транзакцию, после чего me больше не управляется.

У меня есть источники данных xa, и транзакции XA не смешиваются с обычными commit. После того, как я переключился на обычный источник данных, em.createNativeQuery("COMMIT AND CHAIN").executeUpdate() работает как брелок.

Кстати. Я нашел в исходном коде C ++ Arjuna метод chainTransaction, который, похоже, не экспортируется в Java. Но я обнаружил, что он просто делает еще один BEGIN, который, по-видимому, подразумевает COMMIT, так что это может быть портативным способом достижения этого.

...