mybatis一次请求执行多条sql

本文介绍如何在MyBatis中实现单标签内多条SQL语句的执行,并通过配置MySQL连接URL参数允许批量执行,避免语法错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

因为项目需要,需要在mybatis同个标签中执行多条sql语句。如下:

<insert id="insertUser" parameterType="com.test.model.User">  
         insert into user (id,email,name,phone,status) values(#{id,jdbcType=INTEGER},#{email,jdbcType=VARCHAR},#{nick,jdbcType=VARCHAR},#{phone,jdbcType=VARCHAR},#{status,jdbcType=INTEGER});  
         delete from roleuser where userid=#{id,jdbcType=INTEGER};  
         <if test="roles != null and roles.size() != 0 ">  
            insert into roleuser (userid,roleid) values  
            <foreach collection="roles" item="roleId" separator="," close=";">  
                (#{id,jdbcType=INTEGER},#{roleId,jdbcType=INTEGER})  
            </foreach>  
         </if>  
</insert>  
 

寻思着,在mysql中同时执行多条语句时,mysql是一条一条执行的。如果我一次性向mysql发送多条语句,它应该也会这么执行的。

 

我承认一开始想的太简单了,直接这样做的结果,是会在jdbc驱动层面报出语法错误异常,程序无法执行下去。

 

debug后发现,从mybatis拼装sql,到语句传入jdbc驱动,语句都是正常的,但是在mysql驱动验证sql合法性时,sql被截断,它认为一次性发过去的多条sql是不合法的。

 

看了网上很多说法,一说是mybatis本身不支持;一说是mysql驱动不支持。困扰很久,没能解决,后为了项目进度,暂时将sql分开执行了。


<insert id="insertUser" parameterType="com.test.model.User">  
        insert into user (id,email,name,phone,status) values(#{id,jdbcType=INTEGER},#{email,jdbcType=VARCHAR},#{nick,jdbcType=VARCHAR},#{phone,jdbcType=VARCHAR},#{status,jdbcType=INTEGER});  
</insert>  
<delete id="deleteUserById" parameterType="java.lang.Integer">  
        delete from roleuser where userid=#{id,jdbcType=INTEGER};  
</delete>  

前段时间看帖子,发现这样做不行,是因为你没有让mysql驱动开启批量执行sql的开关。

 

怎么开启呢?在拼装mysql链接的url时,为其加上allowMultiQueries参数,设置为true,如下:

 

jdbc.jdbcUrl=jdbc:mysql://127.0.0.1:3306/database?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true

 

加了参数后,我又将mybatis配置文件改了回去,测试一下,执行成功。

 

这里记录一下,希望对看到的人,有所帮助。



附MYSQL 多表更新 语句

UPDATE  A
       LEFT OUTER JOIN
    B ON A.ID = B.ID
LEFT OUTER JOIN
 C ON A.ID = C.ID
SET 
   A.NAME = C.NAME,
   A.TYPE = B.TYPE
WHERE
    A.ID = #{ID}
    AND A.S_ID = #{S_ID}
AND A.P_ID = #{P_ID};



MyBatis执行多条 `update` 语句可以通过多种方式实现。以下是几种常见的方法: ### 方法一:使用 `<foreach>` 标签批量更新 MyBatis 提供了 `<foreach>` 标签来处理集合数据,从而支持批量操作。对于多个 `update` 语句,可以在 SQL 映射文件中定义如下形式的 SQL 语句。 ```xml <update id="batchUpdate" parameterType="java.util.List"> <foreach collection="list" item="item" separator=";" > UPDATE your_table_name SET column1 = #{item.column1}, column2 = #{item.column2} WHERE id = #{item.id} </foreach> </update> ``` 上述代码会针对传入的列表对象逐一生成并执行每一条 `UPDATE` 语句[^1]。 --- ### 方法二:利用数据库事务管理机制 如果需要在一个事务中完成所有的 `update` 操作,则可以借助 Spring 的声明式事务管理功能。通过开启事务,在同一个事务上下文中提交所有修改请求。 #### 配置事务管理器 ```java @Configuration @EnableTransactionManagement public class TransactionConfig { @Bean public PlatformTransactionManager transactionManager(DataSource dataSource) { return new DataSourceTransactionManager(dataSource); } } ``` #### 使用事务注解控制业务逻辑 ```java @Service public class YourService { @Autowired private YourMapper mapper; @Transactional public void batchUpdate(List<YourEntity> entities) { for (YourEntity entity : entities) { mapper.update(entity); // 单独调用 update 方法 } } } ``` 这种方式下,即使有部分失败的情况发生,整个事务也会回滚至初始状态[^3]。 --- ### 方法三:自定义 Mapper 接口配合 XML 实现复杂需求 当面对更复杂的场景时(比如涉及跨表或多条件判断),可以选择手动编写 SQL 并将其封装成独立的方法。 假设存在一张名为 `your_table_name` 的表格,其结构包含字段 `id`, `column1`, 和 `column2`: ```java public interface YourCustomMapper { int customBatchUpdate(@Param("updates") List<Map<String, Object>> updates); } ``` 对应 XML 定义如下所示: ```xml <mapper namespace="com.example.mapper.YourCustomMapper"> <!-- 自定义批处理 --> <update id="customBatchUpdate" parameterType="java.util.List"> <foreach collection="updates" item="updateItem" open="" close="" separator=";"> UPDATE your_table_name SET column1 = #{updateItem['column1']}, column2 = #{updateItem['column2']} WHERE id = #{updateItem['id']} </foreach> </update> </mapper> ``` 此方案允许开发者灵活调整查询逻辑而不受限于框架内置的功能限制[^5]。 --- ### 注意事项 - **性能考量**:大批量的数据更新可能会导致内存占用过高或者锁等待时间过长等问题,因此建议合理规划每次操作的数量规模。 - **异常捕获**:无论采用哪种手段都需要考虑错误恢复策略,确保系统的健壮性和一致性[^4]。 ---
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值