美文网首页
mybatis3.2.8踩坑记录之.size()

mybatis3.2.8踩坑记录之.size()

作者: kevin0016 | 来源:发表于2019-07-29 15:07 被阅读0次

    关于mybatis的xml标签使用问题和单元测试模拟高并发场景

    标签使用问题

    线上问题复现

    Exception in thread "Thread-10" org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 'null!=list and list.size()>0'. Cause: org.apache.ibatis.ognl.MethodFailedException: Method "size" failed for object [3] [java.lang.IllegalAccessException: Class org.apache.ibatis.ognl.OgnlRuntime can not access a member of class com.google.common.collect.Lists$TransformingRandomAccessList with modifiers "public"]
        at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:75)
        at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:368)
        at com.sun.proxy.$Proxy26.selectList(Unknown Source)
        at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:198)
    

    查询对应的xml

    <select id="findUserProductDelaysByOrderNoAndProductId"
            resultMap="BaseResultMap">
            select
            <include refid="Base_Column_List" />
            from pe_user_product_delay where is_deleted = 0
            <if test="null!=list and list.size()>0">
                and status in
                <foreach collection="list" index="index" item="status" open="("
                    separator="," close=")">
                    #{status,jdbcType=INTEGER}
                </foreach>
            </if>
            <if test="productId != null and productId >= 0">
                and product_id =#{productId,jdbcType=INTEGER}
            </if>
            <if test="orderNo != null and orderNo !=''">
                and order_no =#{orderNo,jdbcType=VARCHAR}
            </if>
            and type in (1,2,3)
        </select>
    

    问题就出现在list.size()这上面

    目前的mybatis版本为3.2.8,框架对于传入的集合的调用size方法这部分并发控制的并不好,导致并发量稍微一高就会导致抛出异常,这里有一个关于这个问题的说明

    https://zhuanlan.zhihu.com/p/30085658

    此处建议:

    不要在mybatis的xml中做一些调用集合函数方法等,所有的判断是否为空,判断集合大小这种操作都放到Java代码中执行,现有已存在的代码要尽快修改测试

    单元测试模拟并发环境

    public class UserProductDelayTest extends Junit4Base {
        @Autowired
        private IUserProductDelayService userProductDelayService;
        //模拟短时间内的并发请求量
        private static final int threadNum = 20;
        //倒计时器,用于模拟高并发
        private CountDownLatch cdl = new CountDownLatch(threadNum);
    
        @Test
        public void demo() {
            for (int i = 0; i < threadNum; i++) {
                new Thread(new UserRequest()).start();
                //倒计时计数一次
                cdl.countDown();
            }
            try {
                //阻塞主线程,等待所有的子线程执行完毕
                Thread.currentThread().join();
            } catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        //
        private class UserRequest implements Runnable {
    
            @Override
            public void run() {
                try {
                    cdl.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
              //此处进行写要并发测试的代码
                List<UserProductDelay> delayList =
                      userProductDelayService.findUserProductDelaysByOrderNoAndProductId("123123", 1, UserProductDelay.Status.AUDITEND);
                System.out.println(JSON.toJSONString(delayList));
            }
        }
    }
    
    

    利用CountDownLatch的特性实现模拟并发线程访问,建议所有的对外提供服务的service做单元测试的时候用这种方式自测一下

    相关文章

      网友评论

          本文标题:mybatis3.2.8踩坑记录之.size()

          本文链接:https://www.haomeiwen.com/subject/roubrctx.html