删除记录然后在同一Spring事务中选择仍会返回已删除的记录

时间:2019-01-10 09:06:13

标签: spring hibernate spring-boot jpa hystrix

我在spring事务中有一些代码,隔离级别设置为SERIALIZABLE。该代码先执行一些操作,首先从设置了标志的表中删除所有记录,然后执行选择以确保无效记录无法写入,最后写入新记录。

问题在于,如果代码与事务注释一起运行,则select继续返回已删除的记录。我的理解是,因为我们在同一Spring事务中执行这些操作,因此在执行选择时将考虑先前的删除操作。

我们正在使用Spring Boot 2.1和Hibernate 5.2

代码摘要如下所示:

@HystrixCommand
public void deleteRecord(EntityObj entityObj) {
    fooRepository.deleteById(entityObj.getId());
    //Below line added as part of debugging but I don't think I should really need it?
    fooRepository.flush();
}


public List<EntityObj> findRecordByProperty(final String property) {
    return fooRepository.findEntityObjByProperty(property);
}

@Transactional(isolation = Isolation.SERIALIZABLE)
public void debugReadWrite() {

    EntitiyObject entitiyObject = new EntityObject();
    entitiyObject.setId(1);
    deleteRecord(entitiyObject);
    List<EntityObj> results = findRecordByProperty("bar");
    if (!results.isEmpty()) {
        throw new RuntimeException("Should be no results!")
    }
}

2 个答案:

答案 0 :(得分:1)

事务尚未提交,您需要完成事务,然后找到记录。

用传播= Propagation.REQUIRES_NEW装饰deleteRecord应该可以解决问题

@Transactional(propagation = Propagation.REQUIRES_NEW)
public void deleteRecord(EntityObj entityObj) {
    fooRepository.deleteById(entityObj.getId());
    // flush not needed fooRepository.flush();
}

不需要刷新,因为当deleteRecord完成时,翻译将被提交。

内幕

//start transaction
public void deleteRecord(EntityObj entityObj) {

    fooRepository.deleteById(entityObj.getId());

}
//commit transaction

答案 1 :(得分:1)

原来的问题是由于我们使用Hystrix。事务在Hystirx外部启动,然后在以后通过Hystrix命令执行。 Hystrix命令正在使用线程池,因此在Hystrix线程池中的新线程上执行时,事务丢失。有关更多信息,请参见此github问题: https://github.com/spring-cloud/spring-cloud-netflix/issues/1381