我的 Spring 应用程序中有一个特定的流程调用。
我有一个存储库,并且我在第一次调用时调用了 sell() 方法。
@Service
@Transactional
public class ServiceRepositoryImpl implements ServiceRepository {
@Inject
private SellRepository sellRepository;
@Override
public long sell(long id)
....
....
....
Sell sell = new Sell();
...
sellRepository.save(sell);
}
和我的 SellService:
@Service
public class SellRepositoryImpl implements SellRepository {
@PersistenceContext
private EntityManager entityManager;
@Inject
SellHelperRepository sellHelperRepository;
@Inject
private TransactionTemplate transactionTemplate;
@Override
public <S extends Sell> S save(S sell) throws Exception {
transactionTemplate.execute(new TransactionCallback<S>() {
@Override
public S doInTransaction(TransactionStatus status) {
try {
...
entityManager.persist(sell);
} catch (Throwable e) {
log.error("", e);
status.setRollbackOnly();
}
return vendita;
}
});
sellHelperRepository.createTickets(sell.getId());
return vendita;
}
这是我的 sellHelperRepository:
@Service
@Transactional
public class SellHelperRepositoryImpl implements SellHelperRepository {
@PersistenceContext
private EntityManager entityManager;
@Override
@Async
public void createTickets(long sellID) {
Sell sell = entityManager.find(Sell.class, sellID);
try{
...
Ticket t = new Ticket();
ticketService.save(t);
}catch(Throwable e){
sell.setStatus("CANCELED");
}
}
最后我的ticketService:
@Service
@Transactional
public class TicketRepositoryImpl implements TicketRepository {
@PersistenceContext
protected EntityManager entityManager;
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public Biglietto save(Ticket ticket) throws Exception {
entityManager.persist(ticket);
}
问题是,当我在 SellRepositoryImpl 上时,在这个调用链中,对象销售没有尽快持久化,我已经脱离了交易模板,但它应该是!因此,当我输入 SellHelperRepositoryImpl 并尝试搜索销售时,它没有找到它!
需要这种特殊的结构,因为这些方法也从其他存储库中使用。 我创建了许多 junit 测试用例来检查是否一切正常;对于其余的测试,一切正常,这是这个特定调用链的一部分。
我想我错过了一些东西......
谢谢
最佳答案
您的代码的问题是您在 createTickets
方法上使用了 @Async
,这迫使 Spring 在不同的线程中使用“fresh”执行它事务,因此您需要刷新/提交在 SellRepositoryImpl
类中打开的第一个事务。
所以你可以通过三种方式进行
- 从
createTickets
方法中删除@Async
在
SellHelperRepositoryImpl
中将事务隔离级别从DEFAULT
更改为READ_UNCOMMITTED
@Service @Transactional(isolation=Isolation.READ_UNCOMMITTED) public class SellHelperRepositoryImpl implements SellHelperRepository { @PersistenceContext private EntityManager entityManager; @Override @Async public void createTickets(long sellID) { Sell sell = entityManager.find(Sell.class, sellID); try{ ... Ticket t = new Ticket(); ticketService.save(t); }catch(Throwable e){ sell.setStatus("CANCELED"); } }
在
save(S sell)
中刷新手动管理的交易,请参阅以下代码片段。@Override public <S extends Sell> S save(S sell) throws Exception { transactionTemplate.execute(new TransactionCallback<S>() { @Override public S doInTransaction(TransactionStatus status) { try { ... entityManager.persist(sell); entityManager.getTransaction().commit(); status.flush(); } catch (Throwable e) { log.error("", e); status.setRollbackOnly(); } return vendita; } }); sellHelperRepository.createTickets(sell.getId()); return vendita; }
关于java - 从 @Transaction 方法调用 Spring TransactionTemplate,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31946270/