欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > 【mybatis的批量操作】

【mybatis的批量操作】

2025/2/23 1:50:50 来源:https://blog.csdn.net/m0_50116974/article/details/140758967  浏览:    关键词:【mybatis的批量操作】

在日常开发中,如果要操作数据库的话,或多或少都会遇到批量数据的处理,我们公司使用的mybaits-plus作为持久层的框架,今天就简单介绍一下mybaits批量操作数据库的几种方式。

1.循环插入

其实这种方式并不是批量插入,只是在日常开发中,使用这种方式的还是比较多的。

 代码解读
@RunWith(SpringRunner.class)
@SpringBootTest
public class BatchTest {@Resourceprivate StudentMapper studentMapper;@Testpublic void test(){List<Student> students = generateStudentData(100);long start = System.currentTimeMillis();students.forEach(studentMapper::insert);System.out.println("循环插入: " + students.size() + " 条数据,共计耗时:" + (System.currentTimeMillis() - start) + " 毫秒");}public static List<Student> generateStudentData(int size){List<Student> list = new ArrayList<>(size);Random random = new Random();for (int i = 0; i < size; i++) {Student student = new Student();student.setName("zhangsan-" + i);student.setAge(random.nextInt(40));student.setPhone("15077828899");student.setBirthday(LocalDateTime.now());list.add(student);}return list;}
}

2.foreach方式插入

 代码解读@RunWith(SpringRunner.class)
@SpringBootTest
public class BatchTest {@Resourceprivate StudentMapper studentMapper;@Testpublic void test3(){List<Student> students = generateStudentData(100);long foreachStart = System.currentTimeMillis();studentMapper.insertBatch(students);System.out.println("foreach插入: " + students.size() + " 条数据,共计耗时:" + (System.currentTimeMillis() - foreachStart) + " 毫秒");}public static List<Student> generateStudentData(int size){List<Student> list = new ArrayList<>(size);Random random = new Random();for (int i = 0; i < size; i++) {Student student = new Student();student.setName("zhangsan-" + i);student.setAge(random.nextInt(40));student.setPhone("15077828899");student.setBirthday(LocalDateTime.now());list.add(student);}return list;}
}

StudentMapper 接口如下:

 代码解读public interface StudentMapper extends BaseMapper<Student> {/*** 批量插入*/int insertBatch(@Param("entities") List<Student> entities);/*** 批量更新或者插入*/int insertOrUpdateBatch(@Param("entities") List<Student> entities);}

StudentMapper.xml内容如下:

xml 代码解读<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.efreight.oss.transfer.dao.StudentMapper"><resultMap type="com.efreight.oss.transfer.entity.Student" id="StudentMap"><result property="id" column="id" jdbcType="INTEGER"/><result property="name" column="name" jdbcType="VARCHAR"/><result property="age" column="age" jdbcType="INTEGER"/><result property="birthday" column="birthday" jdbcType="TIMESTAMP"/><result property="phone" column="phone" jdbcType="VARCHAR"/></resultMap><!-- 批量插入 --><insert id="insertBatch" keyProperty="id" useGeneratedKeys="true">insert into cargo.student(name, age, birthday, phone)values<foreach collection="entities" item="entity" separator=",">(#{entity.name}, #{entity.age}, #{entity.birthday}, #{entity.phone})</foreach></insert><!-- 批量插入或按主键更新 --><insert id="insertOrUpdateBatch" keyProperty="id" useGeneratedKeys="true">insert into cargo.student(name, age, birthday, phone)values<foreach collection="entities" item="entity" separator=",">(#{entity.name}, #{entity.age}, #{entity.birthday}, #{entity.phone})</foreach>on duplicate key updatename = values(name) , age = values(age) , birthday = values(birthday) , phone = values(phone)</insert></mapper>

搭配 useGeneratedKeys="true"keyProperty="id" 属性(这个id是javaBean的属性),可以获取自增主键,有时候这个主键我们是非常需要的。

3.批处理方式插入

通过 ExecutorType.BATCH来构建一个可以完成批处理工作的执行器

 代码解读@RunWith(SpringRunner.class)
@SpringBootTest
public class BatchTest {@Resourceprivate StudentMapper studentMapper;@Resourceprivate SqlSessionTemplate sqlSessionTemplate;@Testpublic void test2(){List<Student> students = generateStudentData(100);long batchStart = System.currentTimeMillis();try(SqlSession sqlSession = this.sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false)) {StudentMapper studentMapper = sqlSession.getMapper(StudentMapper.class);for (int i = 0; i < students.size(); i++) {  studentMapper.insert(students.get(i));  if (i % 1000 == 0 || i == students.size() - 1) {  sqlSession.flushStatements();  }  }  sqlSession.commit();}System.out.println("mybatis批处理插入: " + students.size() + " 条数据,共计耗时:" + (System.currentTimeMillis() - batchStart) + " 毫秒");}public static List<Student> generateStudentData(int size){List<Student> list = new ArrayList<>(size);Random random = new Random();for (int i = 0; i < size; i++) {Student student = new Student();student.setName("zhangsan-" + i);student.setAge(random.nextInt(40));student.setPhone("15077828899");student.setBirthday(LocalDateTime.now());list.add(student);}return list;}
}

注意:批处理方式是无法获取自增主键的。

顺便说一下,现在使用mybatis-plus的也非常多,他也提供了批量插入的功能,它内部使用的就是ExecutorType.BATCH 来构建的。

image.png

关于三者性能的比较大家可以跑下看看,循环插入的方式性能最差,能不用就尽量不用,在foreach批处理中,我测试发现foreach的性能最好(我用的MySQL是5.7),所以项目中我们批处理使用的都是foreach, 因为一般我们一般批量插入最多也就2000条左右的数据,但是大家可以根据自己机器的实际情况,去跑一下看看。

插入方式100条1000条10000条10万条
循环插入1599 毫秒14336 毫秒140793 毫秒*
foreach62 毫秒364 毫秒3249 毫秒23940 毫秒
批处理321 毫秒6868 毫秒72851 毫秒457005 毫秒

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词