mysql基础-- 一条请求执行多条SQL语句

MySQL批量执行SQL方法
本文介绍了解决在MySQL中批量执行多条SQL语句时出现的语法错误问题。提供了两种解决方案:一是通过设置连接字符串中的allowMultiQueries参数为true;二是利用程序将SQL语句按分号分割,并使用Statement的addBatch与executeBatch方法执行。
最近做一个 数据库 初始化工具的时候发现了这个问题,就是在一个Statement中执行一条SQL语句的时候可以正确执行,如果同时执行多条,就会报SQL语法错误,伤透了脑筋。 经过网上查找,发现有两种解决办法: 1、最简单的办法,在MySQL的连接字符串中设置allowMultiQueries参数置为true。 2、在程序中对SQL语句以分号拆分成多条SQL语句,然后使用Statement的addBatch方法,最后executeBatch就行。 结论:第一种方式最简单。 希望对以后遇到此类问题的朋友有所帮助。 最近做一个数据库初始化工具的时候发现了这个问题,就是在一个Statement中执行一条SQL语句的时候可以正确执行,如果同时执行多条,就会报SQL语法错误,伤透了脑筋。
    经过网上查找,发现有两种解决办法:
    1、最简单的办法,在MySQL的连接字符串中设置allowMultiQueries参数置为true。
    2、在程序中对SQL语句以分号拆分成多条SQL语句,然后使用Statement的addBatch方法,最后executeBatch就行。
    结论:第一种方式最简单。

    希望对以后遇到此类问题的朋友有所帮助。


转自: http://www.2cto.com/database/201203/121568.html

<think>好的,我现在需要解决用户关于MyBatis-Plus的saveBatch方法如何只执行一条SQL的问题。用户提到他们希望优化批量操作或调整配置,使得saveBatch能够生成并执行单条SQL语句,而不是多次执行。根据用户提供的引用内容,特别是引用[1]和[2],用户遇到的问题是saveBatch实际上并没有生成预期的批量插入SQL,而是逐条插入,导致性能低下。 首先,我需要回忆MyBatis-Plus的saveBatch方法的工作原理。根据引用[1]中的源码,saveBatch方法调用了executeBatch,而这里可能使用了MyBatis的批处理执行器。但默认情况下,MyBatis的批处理执行器(BatchExecutor)并不会将多个插入语句合并成一条SQL,而是通过JDBC的addBatch方法批量执行,这可能在数据库层面仍然是多条语句,但通过批处理减少网络开销。然而,用户期望的是生成像“INSERT INTO ... VALUES (...), (...)”这样的单条SQL,这需要不同的处理方式。 接下来,我需要确认MyBatis-Plus是否支持生成单条批量插入的SQL。根据引用[2]中提到的问题,用户发现saveBatch并没有生成预期的SQL语句,而是逐条插入。这可能是因为MyBatis-Plus默认的批量插入实现并没有将多个值合并到一条INSERT语句中,而是使用了JDBC的批处理,这在某些情况下可能不会转换为单条SQL。 根据引用[3]和[4],用户尝试了添加rewriteBatchedStatements=true参数,但未生效。这可能涉及到JDBC驱动是否支持将批处理操作重写为多值插入语句。例如,MySQL的JDBC驱动在启用rewriteBatchedStatements后,会将多个addBatch的INSERT语句合并成一条,但需要驱动版本和配置正确。如果用户已经尝试过但无效,可能需要检查驱动版本或配置。 用户的问题核心在于如何让saveBatch生成单条SQL,而不仅仅是利用JDBC的批处理。这可能需要自定义MyBatis-Plus的SQL注入器,或者使用其他方法,如手动拼接多值INSERT语句。 我需要考虑以下步骤: 1. 确认MyBatis-Plus的默认行为:是否支持生成单条多值INSERT。 2. 分析JDBC驱动的配置和版本是否影响批处理的重写。 3. 探索自定义批量插入方法的可能性,例如使用MyBatis的foreach标签生成多值INSERT。 4. 考虑第三方工具或插件,如使用MyBatis-Plus的InsertBatchSomeColumn插件。 根据引用[3]和[4],可能需要手动处理字段策略,确保非空字段正确,或者采用异步处理,但这可能不直接解决生成单条SQL的问题。 总结,用户需要调整MyBatis-Plus的配置或使用自定义SQL生成器,以实现单条多值INSERT语句。可能需要指导用户如何配置JDBC参数,或者修改MyBatis-Plus的SQL注入逻辑。同时,需要验证是否MyBatis-Plus有内置的解决方案,如特定的插件或配置选项,或者是否必须手动实现。</think>--- ### MyBatis-Plus 的 `saveBatch` 单条 SQL 实现机制深度解析 --- #### 一、问题核心定位 **`saveBatch` 默认行为**:MyBatis-Plus 的批量插入方法 `saveBatch` 底层基于 MyBatis 的 `BATCH` 执行器,通过 JDBC 的 `addBatch()` 实现批处理,但 **不会生成单条多值 INSERT 语句**(如 `INSERT INTO table VALUES (...), (...)`),而是以批处理形式发送多条 SQL 请求[^1][^2]。 --- #### 二、单条 SQL 实现方案 ##### 方案 1:启用 JDBC 批处理重写(推荐) **适用场景**:MySQL/PostgreSQL 等支持多值 INSERT 的数据库 **实现步骤**: 1. **JDBC 连接参数配置** 添加 `rewriteBatchedStatements=true` 和 `allowMultiQueries=true`: ```yaml # application.yml spring: datasource: url: jdbc:mysql://localhost:3306/test?rewriteBatchedStatements=true&allowMultiQueries=true ``` 2. **MyBatis-Plus 配置验证** ```java @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new BatchInsertInnerInterceptor()); // 增强批处理支持 return interceptor; } ``` **效果验证**: - **日志输出**:观察是否生成 `INSERT INTO table VALUES (...), (...)` - **性能对比**:10 万条数据插入耗时从 30 分钟降至 3-5 秒[^2] ##### 方案 2:自定义批量插入 SQL **适用场景**:需要完全控制 SQL 格式 **实现步骤**: 1. **Mapper 接口定义** ```java public interface UserMapper extends BaseMapper<User> { @Insert("<script>INSERT INTO user (name, age) VALUES " + "<foreach collection='list' item='item' separator=','>(#{item.name}, #{item.age})</foreach></script>") void batchInsert(@Param("list") List<User> list); } ``` 2. **Service 层调用** ```java @Service public class UserService { @Autowired private UserMapper userMapper; @Transactional public void realBatchInsert(List<User> users) { userMapper.batchInsert(users); } } ``` **性能优势**:直接生成单条 SQL,减少网络传输次数。 ##### 方案 3:使用 MyBatis-Plus 扩展插件 **适用组件**:`InsertBatchSomeColumn` 插件(社区扩展) **实现步骤**: 1. **添加依赖** ```xml <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>4.3</version> </dependency> ``` 2. **注入自定义 SQL 注入器** ```java @Configuration public class MybatisPlusConfig { @Bean public InsertBatchSomeColumn insertBatchSomeColumn() { return new InsertBatchSomeColumn(); } } ``` 3. **Mapper 接口声明** ```java public interface UserMapper extends BaseMapper<User> { @InsertBatchSomeColumn int insertBatchSomeColumn(List<User> list); } ``` --- #### 三、关键配置对比 | 方案 | 实现方式 | 优点 | 缺点 | |-----------------------|------------------------------|-------------------------------|-------------------------------| | JDBC 参数优化 | 驱动层自动重写 | 零代码修改,兼容性好 | 依赖数据库和驱动支持 | | 自定义 SQL | 手动编写多值 INSERT 语句 | 完全控制 SQL 格式 | 需要维护动态 SQL 模板 | | 扩展插件 | 社区组件增强 | 语法简洁,接近原生 MyBatis-Plus | 需要引入额外依赖 | --- #### 四、故障排查指南 1. **检查 JDBC 驱动版本** MySQL 8.x 推荐使用 `mysql-connector-java:8.0.28+`,低版本可能不支持批处理重写[^1] 2. **验证参数生效** ```sql SHOW VARIABLES LIKE 'rewriteBatchedStatements'; -- 确认数据库服务端参数 ``` 3. **分析执行日志** 启用 MyBatis SQL 日志: ```yaml mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl ``` --- #### 五、性能优化建议 1. **事务分片提交** ```java int batchSize = 5000; for (int i = 0; i < total; i += batchSize) { List<User> subList = list.subList(i, Math.min(i + batchSize, total)); userService.realBatchInsert(subList); // 每 5000 条提交一次 } ``` 2. **连接池优化** ```yaml spring: datasource: hikari: maximum-pool-size: 20 connection-timeout: 30000 ``` 3. **关闭 MyBatis-Plus 逻辑删除**(非必要字段) ```java @TableLogic(delval = "1", value = "0") private Integer deleted; // 逻辑删除字段会增加 SQL 复杂度 ``` --- #### 六、扩展知识:MyBatis-Plus 批处理原理 通过分析源码 `com.baomidou.mybatisplus.extension.service.impl.ServiceImpl#executeBatch`: ```java protected <E> boolean executeBatch(Collection<E> list, int batchSize, BiConsumer<SqlSession, E> consumer) { try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) { int i = 0; for (E element : list) { consumer.accept(sqlSession, element); if (i >= 1 && i % batchSize == 0) { sqlSession.flushStatements(); } i++; } sqlSession.flushStatements(); } return true; } ``` 该实现通过 `ExecutorType.BATCH` 创建批处理会话,但 **最终是否合并为单条 SQL 取决于 JDBC 驱动实现**[^1][^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值