mybatis使用批量修改语句报错 multi-statement not allow

一、问题解决

    项目里有个功能需要批量更新数据,本想直接在后台for循环里做更新操作,但想起之前看到的最好不要在循环中执行数据库crud操作,因此就改用了直接在mybatis语句中使用foreach来执行批量更新操作(其实性能差不多,都是一条一条去更新),代码如下:
<update id="updateListToNotDelete">
  <foreach collection="userMenus" index="index"  item="item" open="" separator=";" close="">
    update t_sys_user_menu
     set is_delete = 0,version = version+1,
     object_name = #{item.objectName},
     update_date = #{item.updateDate}
     where user_menu_uid = #{item.userMenuUid}
  </foreach>
  </update>
   
  代码没问题吧,但当我执行的时候就有问题了,出现了下面这个错误 multi-statement not allow
 
    
  一脸懵逼的我还以为是执行语句写错了,但检查了好多遍也没发现问题。网上找资料,发现原来是druid配置的问题,要想执行批量更新的操作,需要添加额外的配置。
    首先在数据库连接串后加上:&allowMultiQueries=true
 
jdbc:mysql://192.168.1.129:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=GMT%2B8&allowMultiQueries=true
   
  然后还需要在DruidConfig中添加配置(这个类需要自己新建),    主要是需要添加wallFilter配置
 
/**
* 使用阿里巴巴的Druid配置多数据源
* 需要在配置文件中指定,spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
* @author sxh
* @date 2019年5月5日
* @Description
*
*/
@Configuration
public class DruidConfig {   
     
     @Bean
     @ConfigurationProperties(prefix="spring.datasource")
     public DataSource druidPrimary(){
          DruidDataSource druidDataSource = new  DruidDataSource();
          List<Filter> filterList = new ArrayList<>();
          filterList.add(wallFilter());
          druidDataSource.setProxyFilters(filterList);
          return new DruidDataSource();     
     }    
     
     @Bean
    public WallFilter wallFilter(){
        WallFilter wallFilter = new WallFilter();
        wallFilter.setConfig(wallConfig());
        return wallFilter;
    }
     
     @Bean
    public WallConfig wallConfig() {
        WallConfig config = new WallConfig();
        config.setMultiStatementAllow(true);//允许一次执行多条语句
        config.setNoneBaseStatementAllow(true);//允许一次执行多条语句
        return config;
    }
}
    配置完成,再次执行代码,成功解决!
 

二、另一种方法

    在网上查阅博客的过程中,发现执行批量更新操作还有另外一种方法,就是使用Mybatis的xml去构建sql语句,然后交给数据库执行,这种方法不需要对数据库进行额外的配置,直接上代码:
  
<update id="updateListToNotDelete">
    update t_sys_user_menu
    <trim prefix="set" suffixOverrides=",">
     is_delete = 0,version = version+1,
     <trim prefix="object_name =(case" suffix="end),">
          <foreach collection="userMenus" item="item">
                   <if test="item.objectName != null">
                        when user_menu_uid =  #{item.userMenuUid} then #{item.objectName}
                   </if>
              </foreach>
     </trim>
     <trim prefix="update_date =(case" suffix="end),">
          <foreach collection="userMenus" item="item">
                   <if test="item.updateDate != null">
                        when user_menu_uid =  #{item.userMenuUid} then #{item.updateDate}
                   </if>
              </foreach>
     </trim>
     </trim>
     <where>
          user_menu_uid in
          <foreach collection="userMenus" item="item"  index="index" open="(" separator="," close=")">
              #{item.userMenuUid}
          </foreach>
     </where>
  </update>
    sql最终执行的语句:
#使用SQL一次批量更新多条记录
UPDATE t_sys_user_menu
SET
object_name = (
CASE
WHEN user_menu_uid= 123 then 3
END
),
update_date= (
CASE
WHEN user_menu_uid= 1244 then '111'
END
)
WHERE user_menu_uid IN (123, 1244)

 

 
 
posted @ 2019-09-20 09:09  半城烟雨一城湖  阅读(9173)  评论(0编辑  收藏  举报