Spring事务:内部事务更改被外部事务“回滚”(或者可能是jpa滥用)

时间:2016-07-07 16:02:44

标签: spring hibernate jpa transactions

我有一个简单的代码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块中
  1. 外部交易被暂停
  2. 内部事务提交更改
  3. 内部交易已关闭
  4. 在catch块中抛出异常
  5. 外部交易被回滚
  6. 数据库中的更改包含inner()
  7. 所做的更改

    不幸的是,这不是发生的事情。内/外的所有变化都完全“回滚”。我把引号放在一边因为我认为它不会因为回滚本身而发生。

    如果我更改内部以再次检索实体:

    @Transactional(propagation=REQUIRES_NEW)
    public void inner(MyEntity entity) {
        entity = myRepo.findById(entity.getId());
        // doing something which changes entity
    }
    

    代码开始按预期工作,我确实看到了数据库中inner()所做的更改。

    任何人都可以解释一下为什么这样做以及为什么第一种方法不能按预期工作?

1 个答案:

答案 0 :(得分:1)

Hibernate会话绑定到事务,实体绑定到会话。因此,当您将实体传递给内部方法时,由于它已从外部事务加载,因此它将保持绑定到外部会话。

您发现,不应在事务之间共享实体。

相关问题