我遇到了一个问题,但无法理解原因。当我更新实体的列,然后在同一事务中执行选择查询时,hibernate 会反映对数据库的更改。然而,交易方法尚未完成。场景太长,我尝试用简单的方式解释它。
用户实体
public class User {
@Id
private Long id;
private String name;
private Long depertmantGuid;
}
这里是服务
@Transactional
@Service
public class Service1 {
@Autowired
private Service2 service2;
public void update() {
// other logics
service2.update();
}
}
@Service
public class Service2 {
@Autowired
private UserService userService;
public void update() {
// other logics
userService.update();
}
}
@Service
public class UserService {
public void update() {
User user = userRepo.findByName("user1");
// there are lots of business logic.
user.setName("USER1");
userRepo.save(user);
userRepo.findByDepartmentGuid(1234L);
throw new RuntimeException("to run rollback mechanisim");
}
}
@Repository
public interface UserRepo extends JpaRepository<User, Long> {
User findByName(String name);
List<User> findByDepartmentGuid(Long guid);
}
代码很简单。当我调用
service1.update()
方法时。它先调用 service2
,然后再调用 userService
。 UserService
更新用户行。
当 userRepo.findByDepartmentGuid(1234L);
行工作时,事务仍然打开,以及 hibernate 提交更改的原因。我调试了代码并将光标保留在 userRepo.findByDepartmentGuid(1234L);
行上,在 Oracle 数据库中,该值为 “user1”,在 userRepo.findByDepartmentGuid(1234L);
工作的行之后,数据库中的值为 “USER1”。另外,抛出异常并不能回滚它。
我该如何解决这种情况?
Hibernate 有 4 种不同的刷新模式;
3.3.x版本之后,Hibarnate接受了AUTO刷新模式以避免脏数据。例如;如果在select查询之前相关事务中有更新操作,hibernate会先运行update查询,然后再运行select查询。因此,不会创建脏数据。
如果您不希望这种情况发生,则应将冲洗模式设置为小于10(FlushMode.AUTO)。
因此您需要在properties/yaml文件中更改hibernate的刷新模式。您可以使用此设置来解决您的问题,它会起作用。
spring.jpa.properties.org.hibernate.flushMode = COMMIT