spring事务

如果一个方法A里面还调用了一个方法B,A、B都使用了事务,那么在B事务里面新增的数据,在A方法里面可以查询得到吗?

可以的:事务的传播行为默认是PROPAGATION_REQUIRED,也就是:如果当前没有事务,就新建一个事务;如果已经存在一个事务,那么就加入这个事务。

所以疑惑得到解决:B不会自己再去建立一个事务,而是使用A的事务,由A的事务来管理,只有一个事务A,没有事务B的说法了,所以在一个事务里面新增的数据,在当前事务肯定是可以查询到的。

ps:如果在B方法执行完毕,但是A还没执行完的时候,打一个断点,这个时候在数据库查询是查询不到B方法新增的数据的,因为A方法没有执行完毕,事务还没提交,所以查询不到数据。

 

但是在工作中遇到了一个和上面理论不一样的情况,在这里记录一下:

情况描述:客户需要导入一大批数据到系统,要求导入完成后还要统计所有数据的各项信息总和,比如总的融资金额,总的案件数,案件委案金额超过1万的数量等等。我在设计这个功能的时候,先有一个方法

handleBatchCaseInfo(...),这个方法加了事务,然后在这里方法里面又使用到了多线程,每一个数据使用一个线程来写进数据库,使用
CountDownLatch来监测所有任务都执行完毕了,再从数据库查询刚才插入的数据。
/**
 *多线程异步处理数据    ImportBatchCaseTask 任务里面使用到了事务的
 */
CountDownLatch latch = new CountDownLatch(caseDetailList.size());
for(CaseDetail  caseDetailDemo:caseDetailList){
    ImportBatchCaseTask importBatchCaseTask=new ImportBatchCaseTask(
            latch,
            caseDetailDemo.getCase_sequence_number(),
            caseDetailDemo.getBatch_number(),
            caseDetailDemo.getCollector(),
            caseDetailDemo.getAuthorise_time(),
            caseDetailDemo.getExpected_return_time()
            );
    Executors.newSingleThreadExecutor().execute(importBatchCaseTask);
}
try {
    //等待所有的任务执行完毕
    latch.await();
    //查询该批次的统计数据:总的委案金额、大金额件数、大金额总额、区域件数、区域总额
    List<BatchImportCaseInfo> list=commonService.findListbySqlForObject(BatchImportCaseInfo.class,"select * from batch_case_info where batch_no='"+batchId+"'");
    //问题出现了   list始终为空。

}....

网上看的资料解释不知道是不是对的:在相同线程中进行相互嵌套调用的事务方法工作于相同的事务中。如果这些相互嵌套调用的方法工作在不同的线程中,则不同线程下的事务方法工作在独立的事务中。 解释:开启了多线程的话,多线程里面的事务就是一个个独立的事务。而mysql默认的隔离级别是可重复读,也就是无法读取其他事务提交的内容,这也解释了上面的list始终为空的原因。剩下的就是测试了,是不是把隔离级别改为读已提交,那么list就可以查到数据了呢?

实验:mysql默认的隔离级别是  可重复读  ,我先改为读已提交

set global transaction_isolation='read-committed';
select @@global.transaction_isolation;   --->READ-COMMITTED
然后我在handleBatchCaseInfo(...)方法还是有事务的哈,就只改了隔离级别,测试结果可以获取到值了。

那现在可以得出结论了:

1、多线程情况下,开启的事务是不会和外面的事务有关联的,会自己独立为一个事务。在这些事务里面提交的数据,如果隔离级别是 “可重复读”,那么外面的事务是读取不到的,当然如果外面的方法没有事务,是可以读取到的。

2、多线程情况下,开启的事务是不会和外面的事务有关联的,会自己独立为一个事务。在这些事务里面提交的数据,如果隔离级别是 “读已提交”,那么外面的事务是可以读取。

一般情况是我们不会去改数据库的隔离级别,所以这次我的解决方案是  把handleBatchCaseInfo(...)方法上面的事务不要了,这样子list就可以查询到数据了。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值