Spring JPA无法在一个线程中正确处理多个事务

时间:2018-07-11 08:04:05

标签: java hibernate transactions spring-data-jpa

我有以下代码片段。在我调用BatchSettleService.batchSettleWork(Array.asList([1,2,3]))之后。我发现帐户余额仅减少1(DB)。调试结果是每次accountRepository.findByIdForUpdate(2)返回原始帐户时,在过去的循环中未进行任何更改。我尝试过Isolation.SERIALIZABLE级,但结果是相同的。我正在使用的数据库是MySQL 5.7.20 InnoDb Engine。 JPA实现是Hibernate。我希望减少帐户余额。3.我对交易的理解有问题吗?预先谢谢你!

@Service
public class BatchSettleService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private WorkSettleService workSettleService;

    public List<WorkSettleResponse> batchSettleWork(List<Long> workIds) {
        List<WorkSettleResponse> results= new ArrayList<>();
        for(Long workId:workIds) {
            try {
                results.add(workSettleService.settleWork(new WorkSettleRequest(workId)));
            } catch (WrappedException e) {
                results.add(new WorkSettleResponse(workId,e.getErrCode(),e.getMessage()));
                logger.error("Settle work failed for {}",workId,e);
            }
        }
        return results;
    }

}


   public class WorkSettleService{

        @Autowired
        private AccountRepository accountRepository;

        @Transactional(rollbackFor= {WorkSettleException.class,RuntimeException.class},propagation=Propagation.REQUIRES_NEW)
        public WorkSettleResponse settleWork(WorkSettleRequest req){
             Account account = accountRepository.findByIdForUpdate(2);
             Integer balance = account .getBalance();
             accountRepository.updateBalanceById(account.getId(),balance-1)
        }
    }


    public interface AccountRepository extends Repository<Account, Integer> {

        public Account findById(Integer id);

        @Lock(LockModeType.PESSIMISTIC_WRITE)
        @Query("select ac from Account a where a.id = ?1")
        public Account findByIdForUpdate(Integer id);

        @Modifying
        @Query("update Account a set a.balance = ?2 where a.id = ?1")
        public int updateBalanceById(Integer id,Integer balance);

}

1 个答案:

答案 0 :(得分:0)

此案已解决。 使用account.setBalance(balance-1)代替accountRepository.updateBalanceById(account.getId(),balance-1)。 我不知道为什么@Modifying注释不更新EM缓存,而@Query从EM缓存中获取数据,这对于Spring JPA实现来说有点麻烦。