Ожидание завершения транзакции в Hibernate - PullRequest
0 голосов
/ 05 июня 2019

Рассмотрим следующий (псевдо-kotlin) код:

@Transactional
fun updateDatabase(entity: Entity) {
    // do something with entity
}

fun kafkaProduce() {
    updateDatabase(entity) 
    kafka.sendMessage(entity.id)
}

fun kafkaConsume(entityId: Long) {
    em.find(Entity::class, entityId)
}

Наша проблема в том, что мы используем уровень изоляции READ UNCOMMITTED, который обычно просто в порядке.При вызове kafkaProduce случается, что kafkaConsume вызывается до того, как транзакция в updateDatabase завершается, и она считывает старое состояние сущности.Есть ли способ сделать что-то вроде em.waitForCompletion, чтобы транзакция действительно заканчивалась перед отправкой сообщения в Kafka?

Ответы [ 2 ]

0 голосов
/ 05 июня 2019

Я нашел решение благодаря AlanHay:

    @Transactional
    public void a transactionalMethod() {
        TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter(){
            public void afterCommit(){
                //do stuff right after commit
                System.out.println("commit!!!");

            }
        });

        //do db stuff
    }
0 голосов
/ 05 июня 2019

Если это разные транзакции, вам может понадобиться Пессимистическая блокировка :

fun updateDatabase(entity: Entity) {
   Entity entityMerged = entityManager.merge(entity);
   entityManager.lock(entityMerged, LockModeType.PESSIMISTIC_WRITE);

Это создаст физическую блокировку строки базы данных.Когда другая транзакция попытается запросить эту, а первая еще не завершена, она получит PessimisticLockException.

Затем вы можете поймать его и попытаться восстановить до снятия блокировки.

Только будьте осторожны , чтобы не злоупотреблять этой стратегией и действительно протестировать ее перед началом производства,Это может стать узким местом, если трафик интенсивный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...