mybatis三种批量插入方式对比

xiaoxiao2025-06-01  36

准备:

 1.表结构

CREATE TABLE `t_user` (   `id` varchar(32) CHARACTER SET utf8 NOT NULL COMMENT '主键',   `name` varchar(50) CHARACTER SET utf8 DEFAULT NULL COMMENT '用户名',   `del_flag` char(1) CHARACTER SET utf8 DEFAULT NULL COMMENT '删除标示',   PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

 2.1 jdbc.properties配置

mysql.driver=com.mysql.jdbc.Driver mysql.url=jdbc:mysql://127.0.0.1:3306/ssm mysql.username=root mysql.password=admin #定义初始连接数 mysql.initialSize=1 #定义最大连接数 mysql.maxActive=20 #定义最大空闲 mysql.maxIdle=20 #定义最小空闲 mysql.minIdle=1 #定义最长等待时间 mysql.maxWait=60000

 2.2 spring-mybatis.xml配置

<context:component-scan base-package="com.win.ssm"/> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">     <property name="driverClassName" value="${mysql.driver}"/>     <property name="url" value="${mysql.url}"/>     <property name="username" value="${mysql.username}"/>     <property name="password" value="${mysql.password}"/>     <!-- 初始化链接大小-->     <property name="initialSize" value="${mysql.initialSize}"/>     <!-- 连接池最大数量-->     <property name="maxActive" value="${mysql.maxActive}"/>     <!-- 连接池最大空闲-->     <property name="maxIdle" value="${mysql.maxIdle}"/>     <!-- 连接池最小空闲 -->     <property name="minIdle" value="${mysql.minIdle}"></property>     <!-- 获取连接最大等待时间-->     <property name="maxWait" value="${mysql.maxWait}"/> </bean> <!-- spring与mybatis整合类 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">     <property name="dataSource" ref="dataSource"/>     <!-- 查找接口的别名 -->     <property name="typeAliasesPackage" value="com.win"/>     <!-- 自动扫描mapping.xml文件-->     <property name="mapperLocations" value="classpath:/mapping/*.xml"/> </bean> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">     <constructor-arg index="0" ref="sqlSessionFactory" />     <!--<constructor-arg index="1" value="BATCH" />--> </bean> <!-- 扫描DAO接口 --> <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer">     <property name="basePackage" value="com.win.ssm.dao"/>     <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean> <!-- 事务管理 --> <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager">     <property name="dataSource" ref="dataSource"/> </bean>

第一种:普通for循环插入

 ①junit类

@Test public void testInsertBatch2() throws Exception {     long start = System.currentTimeMillis();     User user;     SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(false);     UserDao mapper = sqlSession.getMapper(UserDao.class);     for (int i = 0; i < 500; i++) {         user = new User();         user.setId("test" + i);         user.setName("name" + i);         user.setDelFlag("0");         mapper.insert(user);     }     sqlSession.commit();     long end = System.currentTimeMillis();     System.out.println("---------------" + (start - end) + "---------------"); }  ②xml配置 <insert id="insert">     INSERT INTO t_user (id, name, del_flag)           VALUES(#{id}, #{name}, #{delFlag}) </insert>

第二种:mybatis BATCH模式插入

 ①junit类

@Test public void testInsertBatch2() throws Exception {     long start = System.currentTimeMillis();     User user;     SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);//跟上述sql区别     UserDao mapper = sqlSession.getMapper(UserDao.class);     for (int i = 0; i < 500; i++) {         user = new User();         user.setId("test" + i);         user.setName("name" + i);         user.setDelFlag("0");         mapper.insert(user);     }     sqlSession.commit();     long end = System.currentTimeMillis();     System.out.println("---------------" + (start - end) + "---------------"); }   ②xml配置与第一种②中使用相同

第三种:foreach方式插入

 ①junit类

@Test public void testInsertBatch() throws Exception {     long start = System.currentTimeMillis();     List<User> list = new ArrayList<>();     User user;     for (int i = 0; i < 10000; i++) {         user = new User();         user.setId("test" + i);         user.setName("name" + i);         user.setDelFlag("0");         list.add(user);     }     userService.insertBatch(list);     long end = System.currentTimeMillis();     System.out.println("---------------" + (start - end) + "---------------"); } ②xml配置 <insert id="insertBatch">     INSERT INTO t_user             (id, name, del_flag)     VALUES     <foreach collection ="list" item="user" separator =",">          (#{user.id}, #{user.name}, #{user.delFlag})     </foreach > </insert>

特别注意:mysql默认接受sql的大小是1048576(1M),即第三种方式若数据量超过1M会报如下异常:(可通过调整MySQL安装目录下的my.ini文件中[mysqld]段的"max_allowed_packet = 1M")

nested exception is com.mysql.jdbc.PacketTooBigException: Packet for query is too large (5677854 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable.

结果对比:      第一种    第二种    第三种 500条    7742    7388    622 1000条    15290    15078    746 5000条    78011    177350    1172 10000条    397472    201180    1205 时间有限测试数据较少,有兴趣可以自己测试以下。(不清楚为什么BATCH有时候比单条循环插入还耗时间,请知道的大神不吝赐教,感谢!) 原文:https://blog.csdn.net/m0_37981235/article/details/79131493   

转载请注明原文地址: https://www.6miu.com/read-5031069.html

最新回复(0)