目录
第一篇、MyBatis批量操作推荐
在工作中使用mybatis操作mysql的时候,难免会有些批量更新或批量插入操作,此时应该启用mybatis的批量查询功能,即设置
allowMultiQueries=true,以及配合mybatis的<foreach></foreach>标签完成批量操作。
例如,在执行批量操作前,先设置配置文件中mysql的连接属性(allowMultiQueries=true):
spring:
datasource:
url: jdbc:mysql://localhost:3306/database_name?characterEncoding=utf8&useSSL=false&allowMultiQueries=true
username: root
password: 123456
driverClassName: com.mysql.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
minimum-idle: 100
maximum-pool-size: 100
max-lifetime: 1800000
idle-timeout: 600000
connection-timeout: 30000
connection-test-query: SELECT 1
data-source-properties:
cachePrepStmts: true
prepStmtCacheSize: 250
prepStmtCacheSqlLimit: 2048
然后,在批量更新操作中,使用如下SQL:
<update id="updateDataByBatch" parameterType = "java.util.List">
<foreach collection="list" index="index" item="item" open="" close=";" separator=";">
UPDATE user_info
SET
name= #{item.name},
password= #{item.password}
WHERE id = #{item.id}
</foreach>
</update>
在批量插入操作中,使用如下SQL:
<insert id="insertDataByBatch" parameterType = "java.util.List">
INSERT INTO user_info (name, password)
VALUES
<foreach collection="list" index="index" item="item" separator=",">
(#{item.name}, #{item.password})
</foreach>
</insert>
第二篇、Mybatisplus真假批量操作
有些同学在mysql的批量操作中,可能还使用了mybatisplus插件提供的api来完成批量操作,分析过源码的同学应该会发现,虽然这些批量操作确实很方便我们的实现,但它是一个伪的“批量操作”,因为底层的实现还是调用的mybatis的单条操作来实现的,因此效率并不高,如insertBatch、insertOrUpdateBatch 、updateBatchById 等,我们来看看其中insertBatch的部分源码:
这是IService接口中批量插入的定义:
/**
* <p>
* 插入(批量),该方法不适合 Oracle
* </p>
*
* @param entityList
* 实体对象列表
* @return boolean
*/
boolean insertBatch(List<T> entityList);
这是ServiceImpl实现类中批量插入的具体实现:
public boolean insertBatch(List<T> entityList) {
return insertBatch(entityList, 30);
}
...
/**
* 批量插入
*
* @param entityList
* @param batchSize
* @return
*/
public boolean insertBatch(List<T> entityList, int batchSize) {
if (CollectionUtils.isEmpty(entityList)) {
throw new IllegalArgumentException("Error: entityList must not be empty");
}
SqlSession batchSqlSession = sqlSessionBatch();
try {
int size = entityList.size();
for (int i = 0; i < size; i++) {
// 此次调用的单条insert方法
baseMapper.insert(entityList.get(i));
if (i % batchSize == 0) {
batchSqlSession.flushStatements();
}
}
batchSqlSession.flushStatements();
} catch (Exception e) {
logger.warn("Error: Cannot execute insertBatch Method. Cause:" + e);
return false;
}
return true;
}
从上面的源码可以看出,mybatisplus插件提供的批量操作其实并不是真正意义上的批处理操作,至少在2.0版本以内不是,其他批量操作也是一样的,我这里就不做赘述了,有兴趣的同学,可以自己去分析源码,并避免使用这些假的“批量操作”。