1

假设我在某处有注释的方法@Transactional(因此开始事务)并且在里面做几个saveAndFlush(). 也许我什至调用了一些依赖项,该依赖项具有通过被注释来启动它自己的(子?嵌套?)事务的方法@Transactional。如果事务在两者之间的某个地方失败,什么会回滚?

一些例子:

public class ComplexProcess {
    @Inject
    private DAO<SomeEntity> someEntityDao;

    @Inject
    private SomeManagerClass manager;

    @Transactional
    public void doStuff(SomeEntity entity) {
        manager.createAnObjectDependingOnEntity(entity);
        entity = someEntityDao.saveAndFlush(entity); // what if this fails?
        manager.doMoreStuffDependingOnEntity(entity);
    }
}

public class SomeManagerClass {

    @Inject
    private DAO<SomeObject> someObjectDao;

    @Inject
    private DAO<SomeOtherEntity> someOtherEntityDao;

    // what if this fails?
    @Transactional // what if this isn't there?
    public void createAnObjectDependingOnEntity(SomeEntity entity) {
        SomeObject someObject = createSomeObjectDependingOnEntity(entity);
        someObjectDao.saveAndFlush(someObject);
    }

    // what if this fails?
    @Transactional // what if this isn't there?
    public void doMoreStuffDependingOnEntity(SomeEntity entity) {
        SomeOtherEntity someOtherEntity = whatever(entity);
        someOtherEntityDao.safeAndFlush(someOtherEntity);
    }
}

再说一遍:如果说最后一步失败了,hibernate 还会回滚之前发生的一切doStuff()吗?因为我有一种感觉,它没有。如果这个完全回滚是不可能的saveAndFlush(),那么在事务结束时使用save()并等待自动刷新会有所帮助吗?我刚刚读到,即使在离开@Transactional块之前,休眠也会在其之间自行进行一些无法控制的刷新?!

4

2 回答 2

9
  • 刷新根本不应该影响事务管理。当事务回滚时,该事务内对数据库状态所做的所有更改(即由 Hibernate 刷新的更改)都将回滚。

  • 的默认传播策略@TransactionalPROPAGATION_REQUIRED。这意味着您可以安全地@Transactional从其他@Transactional方法调用方法,并且它们将使用由顶级事务方法创建的相同事务。如果您明确提供不同的传播设置,情况并非如此。

因此,这意味着在执行顶级@Transactional方法期间发生的任何故障(即从该方法抛出的任何异常)都应该导致回滚,并且在这种情况下应该回滚所有更改。

如果您观察到不同的行为,则可能是配置错误(例如,顶层@Transactional由于某种原因没有生效)。尝试在测试中重现此行为。

于 2013-11-05T11:08:45.600 回答
1

使用您的代码,Hibernate 所做的所有更改都应该回滚,如果某个地方决定回滚当前事务。当然,前提是一切都正确配置。

一些常见的配置问题是: 您persistence.xml应该定义一个JTA持久性单元(而不是 a RESOURCE_LOCAL)并且您的数据库/表应该支持事务(例如 MySQL 表应该使用 InnoDb 搜索引擎)。

于 2013-11-05T11:10:54.143 回答