在Hibernate中等待事务完成

时间:2019-06-05 06:34:25

标签: hibernate jpa

考虑以下(伪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 :(得分:0)

如果它们是不同的交易,那么您可能需要使用悲观锁定

@Entity()
export class Persona {

  @ObjectIdColumn()
  private id:ObjectID

  @Column()
  private nombre:string;

  @Column()
  private edad:number;

  @Column()
  private telefono:string;

  @Column()
  private esCasado:boolean;

  //getters and setters

这将在数据库行上创建物理锁。当其他事务尝试查询该事务而第一个事务仍未完成时,它将获得fun updateDatabase(entity: Entity) { Entity entityMerged = entityManager.merge(entity); entityManager.lock(entityMerged, LockModeType.PESSIMISTIC_WRITE);

然后,您可以抓住它并尝试进行恢复,直到释放锁为止。

请小心,不要过度使用此策略并在投入生产之前对其进行很好的测试。如果交通繁忙,可能会成为瓶颈。

答案 1 :(得分:0)

我通过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
    }