你的位置:首页 > 软件开发 > Java > MyBatis一级缓存引起的无穷递归

MyBatis一级缓存引起的无穷递归

发布时间:2016-04-07 13:00:06
引言:  最近在项目中参与了一个领取优惠劵的活动,当多个用户领取同一张优惠劵的时候,使用了数据库锁控制并发,起初的设想是:如果多个人同时领一张劵,第一个到达的人领取成功,其它的人继续查找是否还有剩余的劵,如果有,继续领取,否则领取失败。在实现中,我一开始使用了递归的方式去查找劵, ...

引言:

  最近在项目中参与了一个领取优惠劵的活动,当多个用户领取同一张优惠劵的时候,使用了数据库锁控制并发,起初的设想是:如果多个人同时领一张劵,第一个到达的人领取成功,其它的人继续查找是否还有剩余的劵,如果有,继续领取,否则领取失败。在实现中,我一开始使用了递归的方式去查找劵,实际的测试中发现出现了无穷递归,通过degug和查阅资料才发现这是由于mybatis的一级缓存引起的,以下将这次遇到的问题和大家分享讨论。

1.知识储备

简单介绍:

Mybatis

一级缓存:默认开启,sqlSession级别缓存,当前会话中有效,执行sqlSession commit()、close()、clearCache()操作后会清除缓存。

二级缓存:需要手工开启,全局级别缓存,与mapper namespace相关。

详情参见:http://www.mamicode.com/info-detail-890951.html

2.代码示例

  以下是一个领取优惠劵的辅助方法-随机抽取一张优惠码,调用这个辅助方法的public方法开启了事务。实际测试的过程中发现,当数据库中只有一张优惠劵时并且同时被多个用户领取时,会出现无穷递归。代码如下:

 1 /** 2    * 随机抽取一张优惠码 3    *  4    * @param codePrefix 5    *      优惠码前缀 6    * @return 优惠码 9   */10   private String randExtractOneTicketCode(String mobile, String codePrefix) {11     List<String> notExchangeCodeList = yzTicketCodeDaoExt.getTicketCodeList(codePrefix,12         MobileServiceConstants.TICKET_CODE_STATUS_NOT_EXCHANGE);13     logger.info("领取优惠劵>>>优惠劵可用数量{}",CollectionUtils.size(notExchangeCodeList));14     if (CollectionUtils.isEmpty(notExchangeCodeList)) {15       logger.warn("领取优惠劵>>>优惠劵{}已领完", codePrefix);16       throw new YzRuntimeException(MobileServiceConstants.TICKET_NOT_REMAINDER);17     }18 19     int randomIndex = random.nextInt(notExchangeCodeList.size()); // 随机的索引20     String ticketCode = notExchangeCodeList.get(randomIndex); // 随机选择的优惠码21     YzTicketCode ticketCodeObj = yzTicketCodeDaoExt.getByCode(ticketCode);22     if (ticketCodeObj == null23         || ticketCodeObj.getStatus() != MobileServiceConstants.TICKET_CODE_STATUS_NOT_EXCHANGE) {24       // 如果优惠劵已被使用25       logger.info("领取优惠劵>>>优惠劵码{}不存在或已被使用",ticketCode);26       return randExtractOneTicketCode(String mobile, String codePrefix);  //递归查找27     }28     /*29      * 更新优惠码状态30     */31     ticketCodeObj.setExchangeTime(Calendar.getInstance().getTime());32     ticketCodeObj.setStatus(MobileServiceConstants.TICKET_CODE_STATUS_HAD_EXCHANGED);33     ticketCodeObj.setMobile(mobile);34     int updateCnt = yzTicketCodeDaoExt.update4Receive(ticketCodeObj);35     if(updateCnt <= 0){36       //乐观锁,没有影响到行,表明更新失败,可能是该劵不存在或已被使用37       logger.info("领取优惠劵>>>优惠劵码{}不存在或已被使用",ticketCode);38       return randExtractOneTicketCode(String mobile, String codePrefix);  //递归查找39     };40     return ticketCode;41   }

原标题:MyBatis一级缓存引起的无穷递归

关键词:缓存

*特别声明:以上内容来自于网络收集,著作权属原作者所有,如有侵权,请联系我们: admin#shaoqun.com (#换成@)。