例子
mybatis批量插入,是拼成一个一次提交还是,多次提交。代码如下
<insert id="addEmpsBatch">
INSERT INTO emp(ename,gender,email,did)
VALUES
<foreach collection="emps" item="emp" separator=",">
(#{emp.eName},#{emp.gender},#{emp.email},#{emp.dept.id})
</foreach>
</insert>
在使用 MyBatis 进行批量插入时,拼成一个 SQL 语句一次性提交 的方式通常比 多次提交 更高效。你的代码示例正是通过 <foreach>
标签将多条插入语句拼接成一个 SQL 语句,然后一次性提交到数据库执行。这种方式减少了与数据库的交互次数,能够显著提升性能。
1. 代码分析
你的代码如下:
xml
复制
<insert id="addEmpsBatch"> INSERT INTO emp(ename, gender, email, did) VALUES <foreach collection="emps" item="emp" separator=","> (#{emp.eName}, #{emp.gender}, #{emp.email}, #{emp.dept.id}) </foreach> </insert>
运行 HTML
-
<foreach>
标签:用于遍历集合emps
,生成多条VALUES
子句。 -
separator=","
:将每条VALUES
子句用逗号分隔,最终拼接成一个完整的 SQL 语句。
生成的 SQL 语句示例:
sql
复制
INSERT INTO emp(ename, gender, email, did) VALUES ('Alice', 'F', 'alice@example.com', 1), ('Bob', 'M', 'bob@example.com', 2), ('Charlie', 'M', 'charlie@example.com', 3);
2. 为什么一次性提交更高效?
-
减少网络开销:
-
一次性提交只需要与数据库交互一次,而多次提交需要多次交互,增加了网络延迟。
-
-
减少事务开销:
-
如果每次插入都单独提交,会导致多次事务提交,增加数据库的事务管理开销。
-
-
数据库优化:
-
数据库对批量插入有优化机制,一次性插入多条数据的性能通常比多次插入更高。
-
3. 注意事项
虽然一次性提交性能更高,但在某些场景下需要注意以下问题:
1. SQL 长度限制
-
数据库对单条 SQL 语句的长度有限制(如 MySQL 的
max_allowed_packet
)。 -
如果批量插入的数据量过大,可能会导致 SQL 语句超长,执行失败。
-
解决方案:
-
将数据分成多个批次,每批次插入一定数量的数据。
-
2. 事务管理
-
如果批量插入过程中某条数据插入失败,默认情况下整个批量插入会回滚。
-
解决方案:
-
如果需要部分成功,可以在代码中捕获异常并处理。
-
3. 数据库性能
-
如果一次性插入的数据量过大,可能会导致数据库锁表或性能下降。
-
解决方案:
-
根据数据库性能调整每批次插入的数据量。
-
4. 改进方案:分批次插入
为了避免 SQL 长度限制和数据库性能问题,可以将数据分批次插入。以下是改进后的代码:
Java 代码
java
复制
public void addEmpsBatch(List<Emp> emps) { SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH); EmpMapper mapper = sqlSession.getMapper(EmpMapper.class); try { for (int i = 0; i < emps.size(); i++) { mapper.addEmp(emps.get(i)); if (i % 1000 == 0 || i == emps.size() - 1) { // 每1000条提交一次 sqlSession.commit(); sqlSession.clearCache(); // 清空缓存,防止内存溢出 } } } catch (Exception e) { sqlSession.rollback(); throw e; } finally { sqlSession.close(); } }
MyBatis Mapper
xml
复制
<insert id="addEmp"> INSERT INTO emp(ename, gender, email, did) VALUES (#{eName}, #{gender}, #{email}, #{dept.id}) </insert>
运行 HTML
5. 性能对比
方式 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
一次性提交 | 性能高,减少网络和事务开销 | SQL 长度限制,可能锁表 | 数据量较小,性能要求高 |
分批次提交 | 避免 SQL 长度限制,减少锁表风险 | 性能略低于一次性提交 | 数据量较大 |
逐条提交 | 实现简单 | 性能差,网络和事务开销大 | 不推荐 |
6. 总结
-
你的代码通过
<foreach>
标签实现了一次性批量插入,性能较高,适合数据量较小的场景。 -
如果数据量较大,建议采用 分批次插入 的方式,避免 SQL 长度限制和数据库性能问题。
-
在实际开发中,需要根据数据量和数据库性能选择合适的批量插入方式。