Mybatis + mysql + Druid批量更新时multi-statement not allow异常

大家好,我是小白学编程。

目录

一、过程

二、原因

三、思路

四、解决办法


一、过程

最近在工作中遇到一个功能,使用 Mybatis 操作 MySql 批量更新时遇到一个报错,就是标题中的这个错误 

***sql injection violation, multi-statement not allow****

我的 xml 是这样写的

<update id="updateStatusBatchById">
		<foreach collection="updateList" item="item" index="index" separator=";" close="">
			update tableName
			set status = #{item.status},update_time = now(),update_login = #{item.updateLogin}
			where vote_id = #{item.id}
		</foreach>
</update>

当遇到这个错误的时候,我下意识的去看一下我的数据库连接串中有没有添加批量操作的配置,也就是  allowMultiQueries=true ,可是很失望,我加了,但是还是有这个错误,也就是说不是这个配置能解决的了的

我的数据库连接串是这样的

url: jdbc:mysql://127.0.0.1:3306/ymdb?autoReconnect=true&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true

于是百度,发现有很多关于这个问题的文章,当我看到这位大佬(在此要感谢各位大佬)的这篇文章后

SpringBoot+Mybatis+Druid批量更新multi-statement not allow异常

对我有了启发,既然是这样,我就可以那样。

二、原因

(以下是我解决完问题之后的个人理解记忆)

        造成这个报错的原因是Druid 数据源中有代理过滤器(ProxyFilter),在这个过滤器中有一个防火墙过滤器(WallFilter),防火墙过滤器中有个防火墙配置(WallConfig),在这个防火墙配置中有一个配置项是 multiStatementAllow ,这个配置项的默认值是 false,就是因为它,导致的不允许一次性执行多条 Sql 语句导致的报错。

三、思路

        既然直到了是这么回事,那我就看看这个配置什么时候初始化的,如果在我能观察到之前就初始化了,我是不是把它改一下就行;如果是在我观察之后才初始化的,是不是我自己设置一下就行了。

        由于我的工程是 SpringBoot 的,通过配置类方式注入的数据源,在我 debug 的时候我发现,在我实例化 DruidDataSource 时 filters 中是没有数据的

那也就是说明,如果我在此处去设置 multiStatementAllow 值是可以的

四、解决办法

        1、在数据库连接串中添加 allowMultiQueries=true 配置,如第二张图

        2、SpringBoot工程在注入数据源时,设置 multiStatementAllow=true

@Bean(name = "mysqlDataSource")
@ConfigurationProperties(prefix = "spring.datasource.mysql")
@Primary
public DataSource writeDataSource() {
    DataSource dataSource = DataSourceBuilder.create().type(dataSourceType).build();
    if(dataSource instanceof DruidDataSource) {
    	DruidDataSource ds = (DruidDataSource)dataSource;
    	WallConfig wallConfig = new WallConfig();
    	wallConfig.setMultiStatementAllow(true);
    	WallFilter wallFilter = new WallFilter();
    	wallFilter.setConfig(wallConfig);
    	List<Filter> filters = Lists.newArrayList(wallFilter);
    	ds.setProxyFilters(filters);
    	return ds;
    }
    return dataSource;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于MybatisMySQL批量插入和批量更新,可以使用以下方法: 1. 批量插入 使用MyBatis的foreach标签,可以很方便地实现批量插入操作。示例如下: ```xml <insert id="batchInsert" parameterType="java.util.List"> insert into my_table (col1, col2, col3) values <foreach collection="list" item="item" separator=","> (#{item.col1}, #{item.col2}, #{item.col3}) </foreach> </insert> ``` 其中,parameterType指定参数类型为List,collection属性指定要插入的List对象,item指定List中的元素,separator指定分隔符。 在Java代码中,调用该方法,将List对象作为参数传入即可。 2. 批量更新 对于批量更新,可以使用MySQL的replace into语句来实现。示例如下: ```xml <update id="batchUpdate" parameterType="java.util.List"> <foreach collection="list" item="item" separator=";"> replace into my_table (id, col1, col2, col3) values (#{item.id}, #{item.col1}, #{item.col2}, #{item.col3}) </foreach> </update> ``` 其中,replace into语句会先尝试插入记录,如果记录已存在,则更新记录。参数类型和调用方式与批量插入相同。 3. 存在即更新 如果只想更新已存在的记录,可以使用MySQL的on duplicate key update语句。示例如下: ```xml <update id="updateIfExists" parameterType="com.example.MyEntity"> insert into my_table (id, col1, col2, col3) values (#{id}, #{col1}, #{col2}, #{col3}) on duplicate key update col1 = values(col1), col2 = values(col2), col3 = values(col3) </update> ``` 其中,id字段为主键。如果该记录已存在,则更新col1、col2、col3字段;否则插入新记录。参数类型为MyEntity,调用方式为传入一个MyEntity对象。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值