1.常用的批量插入的方式
下面的图表展示了mybatis几种方式的批量插入
方式 | 性能 | 说明 |
---|---|---|
for 循环 一个一个插入 | 低,每次都要IO | 普通插入 |
拼装SQL(性能最高、推荐使用) | 高 | 有 SQL 长度限制,定好 List 大小,可以通过下面的语句查询数据包的限制的大小:show variables like '%packet%';show variables like '%net_buffer%'; |
批量插入 | 需要通过sqlSession开启批量插入, SqlSession sqlSession =sqlSessionFactory.openSession(ExecutorType.BATCH, false); |
2.批量插入的测试
初始化环境
@Before
public void setUp() throws Exception {
//创建sqlsessionFactory
String resource = "SqlMapConfig.xml";
//得到配置文件流
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建会话工厂,传入mybatis的配置文件的信息
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
for 循环插入
/**
* 方式一: for 循环 一个一个插入
* @throws Exception
*/
@Test
public void batchInsertTest() throws Exception{
long start = System.currentTimeMillis();
SqlSession sqlSession =sqlSessionFactory.openSession();
//创建userMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
for (int i = 0; i < 100; i++) {
User user= new User();
user.setSex("男");
user.setUsername("sun");
user.setAddress("address");
userMapper.insert(user);
}
sqlSession.commit();
log.info("cost {}ms", System.currentTimeMillis() - start);
//输出日志如下: INFO [main] - cost 1928ms
}
对应的mapper的xml的内容
<insert id="insert" parameterType="com.mybatis.project.po.User">
insert into user (id, username, birthday,
sex, address)
values (#{id,jdbcType=INTEGER}, #{username,jdbcType=VARCHAR}, #{birthday,jdbcType=DATE},
#{sex,jdbcType=CHAR}, #{address,jdbcType=VARCHAR})
</insert>
拼装insert 的SQL语句
@Test
public void insertBatchByConnSql() {
long start = System.currentTimeMillis();
SqlSession sqlSession =sqlSessionFactory.openSession();
//创建userMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = new ArrayList<User>();
for (int i = 0; i < 100; i++) {
User user= new User();
user.setSex("男");
user.setUsername("sun");
user.setAddress("address");
userList.add(user);
}
userMapper.insertBatch(userList);
sqlSession.commit();
log.info("cost {}ms", System.currentTimeMillis() - start);
// INFO [main] - cost 1610ms
}
对应的insertBatch方法中的mapper的xml文件的内容如下:
<insert id="insertBatch" parameterType="list">
insert into user(username,birthday,sex,address) values
<foreach collection="list" item="user" separator=",">
(#{user.username},#{user.birthday},#{user.sex},#{user.address})
</foreach>
</insert>
batch批量插入
注意批量插入的openSession的方法指定了ExecutorType的类型为批量插入,然后事务的自动提交设置为false
如果感兴趣的,可以参考原生的jdbc的批量更新 的方式,可以参考:https://www.jianshu.com/p/c5d7da273c8d的批量更新的章节的内容
//方式三: 执行批量插入,10个一插入
@Test
public void insertBatchByConnectSql() {
long start = System.currentTimeMillis();
SqlSession sqlSession =sqlSessionFactory.openSession(ExecutorType.BATCH, false);
//创建userMapper对象,mybatis自动生成mapper代理对象
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
List<User> userList = new ArrayList<User>();
for (int i = 0; i < 100; i++) {
User user= new User();
user.setSex("男");
user.setUsername("sun");
user.setAddress("address");
userMapper.insert(user);
if (i % 10 == 0 && i != 0) {
sqlSession.commit();
sqlSession.clearCache();
}
}
log.info("cost {}ms", System.currentTimeMillis() - start);
//输出日志如下:INFO [main] - cost 1673ms
}
- 更多的配置细节
参考github的项目mybatis下的mybatis-generator工程下的com.mybatis.bestPractice.batch
地址为: https://github.com/sunkang123/mybatis
总结:可以通过输出的日志发现,每个批量插入的我都加入了执行时间的日志,发现了最短的执行情况为方式二:通过拼装sql的方式,要考虑性能的话,推荐使用拼装的sql,方式二和方式三的区别在于,方式二是一次性发送一个可执行的sql,方式三是一次方式发送多个可执行的sql
网友评论