[聚合文章] mybatis 批量更新

MySQL 2017-12-19 37 阅读

此前的方案在做批量时使用mybatis提供的batch model,该模式下将推迟所有的update(包括insert和delete)语句直到提交事务或者遇到一次查询语句

    @Override    public int doUpdate(MappedStatement ms, Object parameterObject) throws SQLException {      final Configuration configuration = ms.getConfiguration();      final StatementHandler handler = configuration.newStatementHandler(this, ms, parameterObject, RowBounds.DEFAULT, null, null);      final BoundSql boundSql = handler.getBoundSql();      final String sql = boundSql.getSql();      final Statement stmt;      if (sql.equals(currentSql) && ms.equals(currentStatement)) {        int last = statementList.size() - 1;        stmt = statementList.get(last);       handler.parameterize(stmt);//fix Issues 322        BatchResult batchResult = batchResultList.get(last);        batchResult.addParameterObject(parameterObject);      } else {        Connection connection = getConnection(ms.getStatementLog());        stmt = handler.prepare(connection);        handler.parameterize(stmt);    //fix Issues 322        currentSql = sql;        currentStatement = ms;        statementList.add(stmt);        batchResultList.add(new BatchResult(ms, sql, parameterObject));      }    // handler.parameterize(stmt);      handler.batch(stmt);      return BATCH_UPDATE_RETURN_VALUE;    }

上述代码可以看出当使用batch模式时如果sql和上一条sql完全相同(ps),可以复用Statement,因此当批量更新条数越多,性能越赞。对于oracle而言,性能提升可能不会比mysql更明显当开启了pscache的选项后

合并更新执行效率高的主要原因是合并后日志量(MySQL的binlog和innodb的事务让 日志)减少了,降低日志刷盘的数据量和频率,从而提高效率。通过合并SQL语句,同时也能减少SQL语句解析的次数,减少网络传输的IO。

需要注意

  1. SQL语句是有长度限制,在进行数据合并在同一SQL中务必不能超过SQL长度限制,通过max_allowed_packet配置可以修改,默认是1M

  2. 事务需要控制大小,事务太大可能会影响执行的效率。MySQL有innodb_log_buffer_size配置项,超过这个值会把innodb的数据刷到磁盘中,这时,效率会有所下降。所以比较好的做法是,在数据达到这个这个值前进行事务提交。

Icon

通常来说我们使用mybatis采用ReuseExecutor,注意mybatis默认采用SimpleExecutor

可以在mysql连接字符串添加&allowMultiQueries=true

此时即可以做多个更新

    <update id="batchUpdate" parameterType="java.util.List">         <foreach collection="list" item="item" index="index" open="" close="" separator=";">    update test    <set>    test=${item.test}+1    </set>    where id = ${item.id}    </foreach>         </update>

但是当连接字符串加了开关后,包括query也可以查询多个,可能造成查询的结果集错乱,需要避免在query执行多个

对于各位jndi方式的同学来说,打开此开关需要在{tomcat.home}/conf/context.xml修改Resource的url在末尾添加&allowMultiQueries=true

&是html中对&的转义字符,因为><分别是><的转义字符,所以单独要显示&的时候就需要用&

参考文章Mybatis批量更新数据

注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。