spring中使用mybatis实现批量插入的示例代码

有3种实现方式:foreach,spring事务,以及ExecutorType.BATCH.

1. foreach方式

这种方式实际是对SQL语句进行拼接,生成一个长长的SQL,对很多变量进行绑定。如果数据量不大(1000个以内),可以用这种方式。如果数据量太大,可能数据库会报错。

定义接口

public interface StudentMapper05 {
  public void insertStudent(List<Student> studentList);
}

定义mapper

适用于Oracle数据库

<insert id="insertStudent">
  BEGIN
  <foreach collection="list" item="student" index="index" separator="">
    INSERT INTO test_student(ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL)
    VALUES
    (SEQ_ID.nextval, #{student.name}, #{student.branch}, #{student.percentage}, #{student.phone}, #{student.email});
  </foreach>
  END;
</insert>

这个mapper的含义,就是把上送的studentList拼接成一个长SQL,拼成的SQL类似:

BEGIN
INSERT INTO test_student(ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL) VALUES (SEQ_ID.nextval, ?, ?, ?, ?, ?);
INSERT INTO test_student(ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL) VALUES (SEQ_ID.nextval, ?, ?, ?, ?, ?);
INSERT INTO test_student(ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL) VALUES (SEQ_ID.nextval, ?, ?, ?, ?, ?);
...
END;

studentList有几个,就会生成多少个insert语句拼接到一起,每个?都会进行变量绑定,所以当studentList中数据量较多时,生成的SQL会很长,导致数据库执行报错。

dao

public class StudentDao05 {
  private StudentMapper05 studentMapper; // 省略getter和setter

  public void insertStudentList(List<Student> studentList) {
    studentMapper.insertStudent(studentList);
  }
}

beans

mybatis-spring-05.xml:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="oracleDataSource" />
  <property name="configLocation" value="classpath:mybatis/config/mybatis-config-05.xml"/>
</bean>
<bean id="studentMapper05" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="com.ws.experiment.spring.mybatis.mapper.StudentMapper05" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="studentDao05" class="com.ws.experiment.spring.mybatis.dao.StudentDao05">
  <property name="studentMapper" ref="studentMapper05" />
</bean>

main函数

public static void main(String[] args) {
  String[] configFiles = new String[]{"spring-beans-config.xml", "mybatis/mybatis-spring-05.xml"};  // 分别配置datasource和mybatis相关bean
  ApplicationContext context = new ClassPathXmlApplicationContext(configFiles);

  StudentDao05 studentDao = (StudentDao05)context.getBean("studentDao05");

  int counts[] = new int[]{10, 50, 100, 200, 500, 1000, 2000, 3000, 5000, 8000};
  for (int count : counts) {
    List<Student> studentList = new ArrayList<>();
    for (int i = 0; i < count; i++) {
      Student st = new Student();
      st.setName("name");
      st.setBranch("");
      st.setEmail("");
      st.setPercentage(0);
      st.setPhone(0);
      studentList.add(st);
    }
    long startTime = System.currentTimeMillis();
    studentDao.insertStudentList(studentList);
    long endTime = System.currentTimeMillis();
    System.out.println("插入" + count + "笔数据耗时: " + (endTime - startTime) +" ms");
  }
}

测试结果

插入100笔数据耗时: 197 ms
插入200笔数据耗时: 232 ms
插入500笔数据耗时: 421 ms
插入1000笔数据耗时: 650 ms
插入2000笔数据耗时: 1140 ms
插入3000笔数据耗时: 27113 ms
插入5000笔数据耗时: 98213 ms
插入8000笔数据耗时: 301101 ms

2. 借助spring事务

借助spring事务,插入一组数据

开启spring事务

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="oracleDataSource" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

定义接口

public interface StudentMapper06 {
  public void insertStudent(@Param("student") Student student);
}

mapper

<insert id="insertStudent">
  INSERT INTO test_student(ID, NAME, BRANCH, PERCENTAGE, PHONE, EMAIL)
  VALUES
  (SEQ_ID.nextval, #{student.name}, #{student.branch}, #{student.percentage}, #{student.phone}, #{student.email})
</insert>

dao

public class StudentDao06 {
  private StudentMapper06 studentMapper; // 省略getter和setter

  @Transactional // spring事务控制
  public void insertStudentList(List<Student> students) {
    for (Student student : students) {
      studentMapper.insertStudent(student);
    }
  }
}

beans

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="oracleDataSource" />
  <property name="configLocation" value="classpath:mybatis/config/mybatis-config-06.xml"/>
</bean>
<bean id="studentMapper06" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="com.ws.experiment.spring.mybatis.mapper.StudentMapper06" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
<bean id="studentDao06" class="com.ws.experiment.spring.mybatis.dao.StudentDao06">
  <property name="studentMapper" ref="studentMapper06" />
</bean>

main

测试结果

batchInsert001插入10笔数据耗时: 602 ms
batchInsert001插入50笔数据耗时: 196 ms
batchInsert001插入100笔数据耗时: 284 ms
batchInsert001插入200笔数据耗时: 438 ms
batchInsert001插入500笔数据耗时: 944 ms
batchInsert001插入1000笔数据耗时: 1689 ms
batchInsert001插入2000笔数据耗时: 3138 ms
batchInsert001插入3000笔数据耗时: 4427 ms
batchInsert001插入5000笔数据耗时: 7368 ms
batchInsert001插入8000笔数据耗时: 11832 ms

3. 使用ExecutorType.BATCH

基本原理是SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);,设置BATCH方式的sqlSession

有三种设置方式:

3.1 在mybatis的config文件中设置

SqlSessionFactoryBean中可以配置配置文件:

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="oracleDataSource" />
  <property name="configLocation" value="classpath:mybatis/config/mybatis-config-06.xml"/>
</bean>

这个mybatis配置文件中,设置BATCH方式:

<configuration>
  <settings>
    <!-- 默认打开BATCH的Executor -->
    <setting name="defaultExecutorType" value="BATCH" />
  </settings>
  <mappers>
    <mapper class="com.ws.experiment.spring.mybatis.mapper.StudentMapper06" />
  </mappers>
</configuration>

这样,默认打开的sqlSession就都是BATCH方式的。再与spring的事务结合(参看上一节中的spring事务设置),就可以实现批量插入。

测试结果:

batchInsert001插入10笔数据耗时: 565 ms
batchInsert001插入50笔数据耗时: 117 ms
batchInsert001插入100笔数据耗时: 98 ms
batchInsert001插入200笔数据耗时: 106 ms
batchInsert001插入500笔数据耗时: 145 ms
batchInsert001插入1000笔数据耗时: 132 ms
batchInsert001插入2000笔数据耗时: 154 ms
batchInsert001插入3000笔数据耗时: 163 ms
batchInsert001插入5000笔数据耗时: 200 ms
batchInsert001插入8000笔数据耗时: 250 ms

3.2 自己创建sqlSession,手工commit

SqlSessionFactory sqlSessionFactory = (SqlSessionFactory)context.getBean("sqlSessionFactory");
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
StudentMapper06 studentMapper = sqlSession.getMapper(StudentMapper06.class);
for (int i = 0; i < count; i++) {
  Student st = new Student();
  st.setName("name");
  ...
  studentMapper.insertStudent(st);
}
sqlSession.commit();
sqlSession.clearCache();
sqlSession.close();

测试结果:

batchInsert002插入10笔数据耗时: 568 ms
batchInsert002插入50笔数据耗时: 157 ms
batchInsert002插入100笔数据耗时: 132 ms
batchInsert002插入200笔数据耗时: 135 ms
batchInsert002插入500笔数据耗时: 148 ms
batchInsert002插入1000笔数据耗时: 139 ms
batchInsert002插入2000笔数据耗时: 151 ms
batchInsert002插入3000笔数据耗时: 139 ms
batchInsert002插入5000笔数据耗时: 207 ms
batchInsert002插入8000笔数据耗时: 299 ms

3.3 使用sqlSessionTemplate在XML文件中创建bean

创建一个SqlSessionTemplate,然后注入到MapperFactoryBean中,生成对应的mapper:

<!-- 以ExecutorType.BATCH方式插入数据库 -->
<bean id="batchSqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
  <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
  <constructor-arg name="executorType" value="BATCH" />
</bean>
<bean id="studentMapper06_batch" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="com.ws.experiment.spring.mybatis.mapper.StudentMapper06" />
  <property name="sqlSessionTemplate" ref="batchSqlSessionTemplate" />
</bean>
<bean id="studentDao06_batch" class="com.ws.experiment.spring.mybatis.dao.StudentDao06">
  <property name="studentMapper" ref="studentMapper06_batch" />
</bean>

与spring的事务结合后(参看上一节中的spring事务设置),就可以实现批量插入

测试结果

batchInsert003插入10笔数据耗时: 651 ms
batchInsert003插入50笔数据耗时: 133 ms
batchInsert003插入100笔数据耗时: 124 ms
batchInsert003插入200笔数据耗时: 129 ms
batchInsert003插入500笔数据耗时: 144 ms
batchInsert003插入1000笔数据耗时: 179 ms
batchInsert003插入2000笔数据耗时: 229 ms
batchInsert003插入3000笔数据耗时: 241 ms
batchInsert003插入5000笔数据耗时: 216 ms
batchInsert003插入8000笔数据耗时: 259 ms

到此这篇关于spring中使用mybatis实现批量插入的示例代码的文章就介绍到这了,更多相关spring mybatis批量插入内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Mybatis批量修改的操作代码

    1.修改的字段值都是一样的,id不同 <update id="batchUpdate" parameterType="String"> update cbp_order set status=1 where id in <foreach item="id" collection="array" open="(" separator="," close=")&q

  • mybatis执行批量更新batch update 的方法(oracle,mysql两种)

    Oracle和MySQL数据库的批量update在mybatis中配置不太一样: oracle数据库: <code class="hljs tcl" style=""><<span class="hljs-keyword" style="">update</span> id=<span class="hljs-string" style=""

  • Mybatis批量删除多表

    一. 这里主要考虑两种参数类型:数组或者集合. 而这点区别主要体现在EmpMapper.xml文件中标签的collection属性: 当collection="array"时,表名参数为数组; 当collection="list"时,表名参数为集合. 二. 注意: 无论Mybatis是与mysql数据库结合,还是与Oracle数据库,都同样适合如下设置与操作. 三. 具体示例如下: EmpMapper.xml: <!-- 批量删除员工信息 --> <

  • 详解mybatis 批量更新数据两种方法效率对比

    上节探讨了批量新增数据,这节探讨批量更新数据两种写法的效率问题. 实现方式有两种, 一种用for循环通过循环传过来的参数集合,循环出N条sql, 另一种 用mysql的case when 条件判断变相的进行批量更新 下面进行实现. 注意第一种方法要想成功,需要在db链接url后面带一个参数  &allowMultiQueries=true 即:  jdbc:mysql://localhost:3306/mysqlTest?characterEncoding=utf-8&allowMulti

  • mybatis中批量插入的两种方式(高效插入)

    MyBatis简介 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(Plain Old Java Objects,普通的Java对象)映射成数据库中的记录. 一.mybiats foreach标签 foreach的主要用在构建in条件中,它可以在SQL语句中进行迭代一个集合.foreach元素的属性主

  • MyBatis批量插入(insert)数据操作

    在程序中封装了一个List集合对象,然后需要把该集合中的实体插入到数据库中,由于项目使用了Spring+MyBatis的配置,所以打算使用MyBatis批量插入,由于之前没用过批量插入,在网上找了一些资料后最终实现了,把详细过程贴出来. 实体类TrainRecord结构如下: public class TrainRecord implements Serializable { private static final long serialVersionUID = -12069604621179

  • MyBatis批量插入数据到Oracle数据库中的两种方式(实例代码)

    一.mybatis批量插入数据到Oracle中的两种方式: 第一种: <insert id="addList" parameterType="java.util.List" useGeneratedKeys="false"> INSERT ALL <foreach item="item" index="index" collection="list"> INTO

  • Mybatis批量更新报错问题

    下面给大家介绍mybatis批量更新报错问题, allowMultiQueries=true 后来发现是jdbc链接没有加允许批量更新操作的参数引起的,不加会报badsql,mysql版的mybatis批量更新操作如下 <update id="updateOrderOverdueStatus" parameterType="java.util.List"> <foreach collection="list" item=&quo

  • Mybatis 插入一条或批量插入 返回带有自增长主键记录的实例

    首先讲一下, 插入一条记录返回主键的 Mybatis 版本要求低点,而批量插入返回带主键的 需要升级到3.3.1版本,3.3.0之前的都不行. <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>3.3.1</version> </dependency> 1.MySQL <

  • Mybatis批量更新三种方式的实现

    Mybatis实现批量更新操作 方式一: <update id="updateBatch" parameterType="java.util.List"> <foreach collection="list" item="item" index="index" open="" close="" separator=";">

  • MyBatis批量添加、修改和删除

    废话不多说了,直接步入正题了. 1.批量添加元素session.insert(String string,Object o) public void batchInsertStudent(){ List<Student> ls = new ArrayList<Student>(); for(int i = 5;i < 8;i++){ Student student = new Student(); student.setId(i); student.setName("

  • Mybatis中使用updateBatch进行批量更新

    背景描述:通常如果需要一次更新多条数据有两个方式,(1)在业务代码中循环遍历逐条更新.(2)一次性更新所有数据(更准确的说是一条sql语句来更新所有数据,逐条更新的操作放到数据库端,在业务代码端展现的就是一次性更新所有数据).两种方式各有利弊,下面将会对两种方式的利弊做简要分析,主要介绍第二种方式在mybatis中的实现. 逐条更新 这种方式显然是最简单,也最不容易出错的,即便出错也只是影响到当条出错的数据,而且可以对每条数据都比较可控,更新失败或成功,从什么内容更新到什么内容,都可以在逻辑代码

随机推荐