MySql数据批量导入:批量导入数据时一般会将rewriteBatchedStatements设置为true
对参数rewriteBatchedStatements解释:
MySQL的JDBC连接的url中要加rewriteBatchedStatements参数,并保证5.1.13以上版本的驱动,才能实现高性能的批量插入。
MySQL JDBC驱动在默认情况下会无视executeBatch()语句,把我们期望批量执行的一组sql语句拆散,一条一条地发给MySQL数据库,批量插入实际上是单条插入,直接造成较低的性能。
只有把rewriteBatchedStatements参数置为true, 驱动才会帮你批量执行SQL
另外这个选项对INSERT/UPDATE/DELETE都有效
idea创建maven工程,导入mybatis依赖,单元测试依赖等
pom.xml
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<version>5.1.47version>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
<scope>testscope>
dependency>
<dependency>
<groupId>org.mybatisgroupId>
<artifactId>mybatisartifactId>
<version>3.5.6version>
dependency>
实体类
@Data
public class Student {
private int id;
private String username;
}
(for循环,每遍历一次,就执行一条插入的SQL语句,性能差,效率低)
@Test
public void add () throws IOException {
InputStream is = Resources.getResourceAsStream ( "mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ( ).build ( is);
SqlSession sqlSession = sqlSessionFactory.openSession ( );
StudentDao mapper = sqlSession.getMapper ( StudentDao.class );
List<Student> list = new ArrayList<> ( );
for (int i = 0; i < 5; i++) {
Student student = new Student ( );
student.setUsername ( "张三" + i );
list.add ( student );
}
for (int i = 0; i < list.size ( ); i++){
mapper.addOne ( list.get ( i ) );
}
sqlSession.commit ( );//插入数据需要手动提交事务
sqlSession.close ( );//释放资源
}
StudentDao.xml
<insert id="addOne" parameterType="student">
insert into student values (null,#{username})
insert>
控制台打印执行的SQL语句如下:
Checking to see if class com.itheima.mapper.StudentDao matches criteria [is assignable to Object]
Opening JDBC Connection
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@62fdb4a6]
==> Preparing: insert into student values (null,?)
==> Parameters: 张三0
<== Updates: 1
==> Preparing: insert into student values (null,?)
==> Parameters: 张三1
<== Updates: 1
==> Preparing: insert into student values (null,?)
==> Parameters: 张三2
<== Updates: 1
==> Preparing: insert into student values (null,?)
==> Parameters: 张三3
<== Updates: 1
==> Preparing: insert into student values (null,?)
==> Parameters: 张三4
<== Updates: 1
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@62fdb4a6]
Process finished with exit code 0
插入多条数据,只执行一次SQL语句,使用foreach标签拼接参数
当参数列表较多时,使用foreach插入,性能会比较差
public void add () throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream ( resource );
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ( ).build ( inputStream );
SqlSession sqlSession = sqlSessionFactory.openSession ( );
StudentDao mapper = sqlSession.getMapper ( StudentDao.class );
List<Student> list = new ArrayList<> ( );
for (int i = 0; i < 5; i++) {
Student student = new Student ( );
student.setUsername ( "张三" + i );
list.add ( student );
}
mapper.addList ( list );
sqlSession.commit ( );
sqlSession.close ( );
}
StudentDao.xml中编写addList方法的SQL语句
<insert id="addList" parameterType="list">
insert into student values
<foreach collection="list" separator="," item="s" >
(null,#{s.username})
foreach>
insert>
控制台打印执行的SQL语句如下:
Opening JDBC Connection
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@731f8236]
==> Preparing: insert into student values (null,?) , (null,?) , (null,?) , (null,?) , (null,?)
==> Parameters: 张三0(String), 张三1(String), 张三2(String), 张三3(String), 张三4(String)
<== Updates: 5
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@731f8236]
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@731f8236]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@731f8236]
ExecutorType 参数是枚举类型。这个枚举类型定义了三个值:
ExecutorType.SIMPLE:该类型的执行器没有特别的行为。它为每个语句的执行创建一个新的预处理语句。
ExecutorType.REUSE:该类型的执行器会复用预处理语句。
ExecutorType.BATCH:该类型的执行器会批量执行所有更新语句,如果 SELECT 在多个更新中间执行,将在必要时将多条更新语句分隔开来,以方便理解。
注意
开启ExecutorType.BATCH模式:
在创建连接时,传入参数ExecutorType.BATCH即可开启ExecutorType.BATCH模式
(默认为simple模式)
SqlSession sqlSession = sqlSessionFactory.openSession ( ExecutorType.BATCH);
即使使用for循环单次添加,也会先将数据添加到缓存中,等待commit时再将所有数据保存到数据库中
@Test
public void add () throws IOException {
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream ( resource );
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder ( ).build ( inputStream );
SqlSession sqlSession = sqlSessionFactory.openSession ( ExecutorType.BATCH);
StudentDao mapper = sqlSession.getMapper ( StudentDao.class );
List<Student> list = new ArrayList<> ( );
for (int i = 0; i < 5; i++) {
Student student = new Student ( );
student.setUsername ( "张三" + i );
list.add ( student );
}
for (Student student : list) {
mapper.add ( student );
}
sqlSession.commit ( );
sqlSession.close ( );
}
Opening JDBC Connection
Setting autocommit to false on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1372ed45]
==> Preparing: insert into student values (null,?)
==> Parameters: 张三0(String)
==> Parameters: 张三1(String)
==> Parameters: 张三2(String)
==> Parameters: 张三3(String)
==> Parameters: 张三4(String)
Committing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1372ed45]
Resetting autocommit to true on JDBC Connection [com.mysql.jdbc.JDBC4Connection@1372ed45]
Closing JDBC Connection [com.mysql.jdbc.JDBC4Connection@1372ed45]
对于foreach和数据库批量执行效率:
参考:foreach 和 数据库批量执行 效率比较