MyBatis批量执行(不是foreach遍历),以及解决通用Mapper的坑

说到MyBatis的批量插入、修改相信很多人会说使用foreach遍历集合,然后去执行SQL语句;或者在XML中去使用foreach标签拼接SQL语句然后执行。其实这不是批量执行,而只能称之为是遍历执行。那么怎么才是批量执行呢?答案就在MyBatis官方文档中写着呢!http://www.mybatis.org/mybatis-3/configuration.html#settings

 

defaultExecutorType Configures the default executor. SIMPLE executor does nothing special. REUSE executor reuses prepared statements. BATCH executor reuses statements and batches updates. SIMPLE REUSE BATCH SIMP

答案就是设置defaultExecutorType为BATCH,默认是SIMPLE。但是需要注意的是这是一个全局配置一般情况下,我们使用的是SIMPLE。如果我们有批量执行的需求,可以单独注入一个SqlSessionTemplate,其参数executorType设置为BATCH,然后使用即可。

XML中的SqlSessionTemplate,需要在Java代码中注入获取


  

Java代码:

@Autowired
SqlSessionTemplate sqlSessionTemplate;

@Test
public void testSqlSessionBatch() {
        long start = System.currentTimeMillis();
        try (SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory()
                .openSession(ExecutorType.BATCH, false)) {
            // 需要注意的是一个SqlSession只能做一件事,比如全部是insert,否则批处理失效
            BwJdqBasicMapper mapper = sqlSession.getMapper(BwJdqBasicMapper.class);
            for (int i = 0; i < 100; i++) {
                BwJdqBasic bwJdqBasic = new BwJdqBasic();
                bwJdqBasic.setRealName("" + i);
                bwJdqBasic.setGmtCreate(new Date(System.currentTimeMillis()));
                bwJdqBasic.setGmtModified(new Date(System.currentTimeMillis()));

                mapper.insert(bwJdqBasic);
            }
            
            sqlSession.commit();
        } catch (Exception e) {
            e.printStackTrace();
            logger.info("异常:{}", e.getMessage());
        }
        long end = System.currentTimeMillis();
        logger.info("结束时间:{}", end - start);
}

那么上面的sqlSession就是一个有批处理功能的。另外再提一句,这个已经是批处理了,但是其执行效率很低,如果要想提高效率,可以在

jdbc:mysql://127.0.0.1:3306/project?rewriteBatchedStatements=truerewriteBatchedStatements=true

中添加rewriteBatchedStatements=true参数,这样效率大大提高(90%的人真的不知道,开个玩笑)。

 

补充(2018-05-30):

在使用批处理的时候发现一个问题,就是项目中使用了个人第三方“框架”(通用Mapper)导致批处理失效。

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY, generator = "JDBC")
private Long id;

 

上面的主键id的生成策略中在通用Mapper中必须要加generator = "JDBC"才能生效,而strategy则随便,简直是坑爹啊!!!

 

针对这个问题我还在作者的Github上面提问,但是没有得到回复:https://github.com/abel533/Mapper/issues/312

 

注:
另外插一嘴,个人不建议在企业中使用这样的框架,否则出现问题很难搞。

你可能感兴趣的:(Java之MyBatis)