假设我的某个地方有注释@Transactional
(因此启动了一个事务)并在里面做了几个saveAndFlush()
。也许我甚至调用一些依赖项,该依赖项具有一个方法,通过注释@Transactional
来启动它自己的(sub?nested?)事务。如果事务在两者之间的某个地方失败,那么会回滚什么?
一些例子:
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
块之前,hibernate也会在它们之间进行一些无法控制的刷新?!
答案 0 :(得分:7)
刷新不应影响所有的交易管理。当回滚事务时,将回滚对该事务中对数据库状态所做的所有更改(即,由Hibernate刷新的更改)。
@Transactional
的默认传播政策为PROPAGATION_REQUIRED
。这意味着您可以安全地从其他@Transactional
方法调用@Transactional
方法,并且它们将使用由顶级事务方法创建的相同事务。如果您明确提供不同的传播设置,情况并非如此。
因此,这意味着在执行顶级@Transactional
方法期间发生的任何失败(即从该方法抛出的任何异常)都应该导致回滚,并且在这种情况下应该回滚所有更改。
如果您观察到不同的行为,可能是某些内容配置错误(例如,顶级@Transactional
因某种原因无法生效)。尝试在测试中重现此行为。
答案 1 :(得分:1)
使用您的代码,Hibernate所做的所有更改都应该回滚,如果某个地方决定回滚当前事务。当然,只有一切都正确配置。
一些常见的配置问题是:
您的persistence.xml
应该定义JTA
持久性单元(而不是RESOURCE_LOCAL
),并且您的数据库/表应该支持事务(例如,MySQL表应该与InnoDb搜索引擎一起使用)。