UPD 1:经过进一步研究,我认为以下信息可能有用:
我通过WildFly 9.0.2上的JNDI查找获得数据源,然后将其“包装”到HikariDataSource实例中(例如, return new HikariDataSource(jndiDSLookup(dsName)) )。
最终使用的事务管理器是JTATransactionManager 。
我不以任何方式配置事务管理器。
原始问题:
我遇到了JPA / Hibernate和(也许)Spring-Boot的问题,其中即使回退了调用方方法中的更改,也提交了从另一类的事务处理方法调用的一类事务处理方法中引入的数据库更改。他们应该是)。
这是我的交易服务
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 findOne(/* some criteria */);
}
FirstCustomException扩展了Throwable
SecondCustomException扩展了RuntimeException
Stuff实体经过版本控制,并且每隔一段时间由StuffService.updateStuff()同时更新。 在那种情况下,对stuff实例之一的更改将按预期回滚,但是barService.doBar()中发生的所有事情最终都会被提交。
这让我为难了不少,因为在这两种方法事务传播应REQUIRED (默认的),而且这两种方法都属于不同的类别,因此@Transactional应同时申请。
但这并没有真正回答我的问题。
谁能告诉我发生了什么事?
谢谢。