【发布时间】:2016-06-16 14:02:35
【问题描述】:
UPD 1:经过进一步研究,我认为以下信息可能有用:
- 我通过 WildFly 9.0.2 上的 JNDI 查找获取数据源,然后将其“包装”到
HikariDataSource的实例中(例如return new HikariDataSource(jndiDSLookup(dsName)))。 - 最终被使用的事务管理器是
JTATransactionManager。 - 我没有以任何方式配置事务管理器。
原始问题:
我遇到了 JPA/Hibernate 和(可能)Spring-Boot 的问题,其中在从另一个类的事务方法调用的一个类的事务方法中引入的 DB 更改被提交,即使调用者方法中的更改被滚动返回(应该如此)。
这是我的交易服务
StuffService:
@Service
@Transactional(rollbackFor = IOException.class)
public class StuffService {
@Inject private BarService barService;
@Inject private StuffRepository stuffRepository;
public Stuff updateStuff(Stuff stuff) {
try {
if (null != barService.doBar(stuff)) {
stuff.setSomething(SOMETHING);
stuff.setSomethingElse(SOMETHING_ELSE);
return stuffRepository.save(stuff);
}
} catch (FirstCustomException e) {
logger.error("Blah", e);
throw new SecondCustomException(e.getMessage());
}
throw new SecondCustomException("Blah 2");
}
// other methods
}
和BarService:
@Service
@Transactional
public class BarService {
@Inject private EntityARepository entityARepository;
@Inject private EntityBRepository entityBRepository;
/*
* updates existing entity A and persists new entity B.
*/
public EntityA doBar(Stuff stuff) throws FirstCustomException {
EntityA a = entityARepository.findOne(/* some criteria */);
a.setSomething(SOMETHING);
EntityB b = new EntityB();
b.setSomething(SOMETHING);
b.setSomethingElse(SOMETHING_ELSE);
entityBRepository.save(b);
return entityARepository.save(a);
}
// other methods
}
EntityARepository 和 EntityBRepository 是非常相似的 Spring-Boot 存储库,定义如下:
public interface EntityARepository extends JpaRepository<EntityA, Long>{
EntityA findOne(/* some criteria */);
}
FirstCustomException 扩展Throwable
SecondCustomException 扩展 RuntimeException
Stuff 实体是版本化的,并且每隔一段时间它就会由StuffService.updateStuff() 并发更新。在这种情况下,对stuff 实例之一的更改按预期回滚,但barService.doBar() 中发生的所有事情最终都会被提交。
这让我很困惑,因为这两种方法上的事务传播都应该是REQUIRED(默认方法)并且两种方法都属于不同的类,因此@Transactional 应该适用于两者。
我确实看到了Transaction is not completely rolled back after server throws OptimisticLockException1
但它并没有真正回答我的问题。
谁能告诉我发生了什么?
谢谢。
【问题讨论】:
-
什么错误/异常导致其中一项服务回滚?
-
@Mubin:
OptimisticLockException,这是由StaleObjectStateException引起的,完全可以预见。