Mybatis對緩存提供支持,是默認開啟一級緩存。
來一段代碼,這邊使用的是mybatis-plus框架,通過構建 QueryWrapper 查詢類來實現的。
1 @Transactional 2 public ResData assginOrder1(List<SaleAssignData> assignlist) { 3 4 //此處省略很多代碼 5 LocalDateTime now = LocalDateTime.now(); 6 assignlist.stream().forEach(data -> { 7 Integer projectId = data.getProjectId(); 8 Integer count = data.getCount(); 9 if(count != null && count >0){ 10 List<OrderDetailDO> list = orderDetailMapper.selectList(new QueryWrapper<OrderDetailDO>() 11 .eq("project_id", projectId).eq("agent_id", userId) 12 .eq("status",0).orderByAsc("id").last("limit" + count)); 13 14 Integer saleId = data.getUserId(); 15 SysUserDO saleman = sysUserMapper.selectById(saleId); 16 17 list.stream().forEach(orderDetailDO ->{ 18 //此處list處理 19 }); 20 orderDetailService.saveOrUpdateBatch(list); 21 } 22 }); 23 24 //此處其他表操作 25 26 return new ResData(); 27 }
如果傳入的參數assignlist
[ { "projectId":1, "saleId":1, "count":1 }, { "projectId":1, "saleId":2, "count":1 } ]
在同一事務,兩次查詢條件,projectId和count值一樣,原本認為第一次查詢出的結果會被修改,可以順利的修改成功。但事與願違,兩次查詢得到的數據結果是一樣,兩次修改的是同一條數據,這就是因為mybatis一級緩存機制導致。
那么,怎么解決呢?以下提供兩個方法
方法一:使用隨機數方式,在sql處拼接一段隨機數 【 .apply(num+"="+num) 】 ,讓mybatis認為sql不一樣
Random rn = new Random();
int num = rn.nextInt(100000);
List<OrderDetailDO> list = orderDetailMapper.selectList(new QueryWrapper<OrderDetailDO>().apply(num+"="+num) .eq("project_id", projectId).eq("agent_id", userId) .eq("status",0).orderByAsc("id").last("limit "+count));
方法二:springboot配置不使用一級緩存(默認是session級別),但是使用這種情況,一級緩存都不能使用,每次查詢都要去數據庫查詢
mybatis.configuration.local-cache-scope=statement
這樣就可以得到很好的解決。