我有一个简单的代码spring + jpa,乍一看看是正确的:
@Transactional(propagation=REQUIRED)
public void outer(long id) {
MyEntity entity = myRepo.findById(id);
try {
// doing something that changes entity
// and may throw exception
doInOuter(entity);
} catch (Exception ex) {
anotherSpringService.inner(entity);
throw ex; // this rollbacks outer transaction for sure
}
}
@Transactional(propagation=REQUIRES_NEW)
public void inner(MyEntity entity) {
// doing something that changes entity
}
让我们考虑在doInOuter()期间发生异常的情况。我希望在inner()
中的catch块中不幸的是,这不是发生的事情。内/外的所有变化都完全“回滚”。我把引号放在一边因为我认为它不会因为回滚本身而发生。
如果我更改内部以再次检索实体:
@Transactional(propagation=REQUIRES_NEW)
public void inner(MyEntity entity) {
entity = myRepo.findById(entity.getId());
// doing something which changes entity
}
代码开始按预期工作,我确实看到了数据库中inner()所做的更改。
任何人都可以解释一下为什么这样做以及为什么第一种方法不能按预期工作?
答案 0 :(得分:1)
Hibernate会话绑定到事务,实体绑定到会话。因此,当您将实体传递给内部方法时,由于它已从外部事务加载,因此它将保持绑定到外部会话。
您发现,不应在事务之间共享实体。