我在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!")
}
}
答案 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