2500-使用MyBatis操作MySQL进行批量更新的注意事项

原则上一条SQL只更新一条数据库操作,但有时需要批量操作数据,特别是一些DML语句,在操作数据库时,数据库会报出异常,不允许混合语句,此时需要额外配置进行兼容。

例如:

Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'update purchase_instrument_bill_detail   
                 SET out_count = '1',
' at line 8

Caused by: java.sql.SQLException: sql injection violation, multi-statement not
allowcom.alibaba.druid.wall.WallFilter.check(WallFilter.java:714) 
atcom.alibaba.druid.wall.WallFilter.connection_prepareStatement(WallFilter.java:240) 
atcom.alibaba.druid.filter.FilterChainImpl.connection_prepareStatement(FilterChainImpl.java:448)
atcom.alibaba.druid.filter.FilterAdapter.connection_prepareStatement(FilterAdapter.java:928) 

解决方案:

  1. 数据库连接加参数
  2. 连接池需要配置

1. 数据库连接加参数

添加参数allowMultiQueries=true

可解决数据库连接层面的异常问题,指定连接数据库时,可执行混合SQL。

参考连接配置: jdbc:mysql://({datasource.host}:){datasource.port}/${datasource.name}?relaxAutoCommit=true&useUnicode=true&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&autoReconnect=true&failOverReadOnly=false&useSSL=false&allowMultiQueries=true

2. 连接池需要配置

如果使用的数据库连接池是Druid,则需要额外配置参数。其他种类连接池,如C3P0,DBCP等,尚未考证。

## 配置监控统计拦截的filters,去掉后监控界面sql无法统计,'wall'用于防火墙,此处去除防火墙
spring.datasource.druid.filters=config,stat,slf4j
## 配置过滤器wall的参数
spring.datasource.druid.filter.wall.config.use-allow=false
spring.datasource.druid.filter.wall.config.multi-statement-allow=true

wall是com.alibaba.druid.wall.WallFilter的简称,提供sql的检查和过滤等功能,默认这里会对混合SQL进行拦截,此处为了执行大SQL,可关闭防火墙功能。(有SQL注入风险,谨慎使用)


附上一个MyBatis的xml脚本demo:


    <update id="batchUpdateForRepay" parameterType="com.xxx.settle.credit.generate.domain.bo.RepayUpdateCreditInfoBO">

        <foreach collection="list" index="index" item="item" separator=";">
            update tb_credit_info
            <trim prefix="set" suffixOverrides=",">
                <if test="item.state != null">state = #{item.state},</if>
                <if test="item.leftPrincipalAmount != null">left_principal = left_principal - #{item.leftPrincipalAmount},</if>
                <if test="item.currentPeriodChange != null">current_period = current_period + #{item.currentPeriodChange},</if>
                <if test="item.receivedPrincipalAmount != null">received_principal = received_principal + #{item.receivedPrincipalAmount},</if>
                <if test="item.remark != null">remark = #{item.remark},</if>
            </trim>
            where product_id = #{item.productId} and credit_id = #{item.creditId}
        </foreach>

    </update>
原文地址:https://www.cnblogs.com/starmoon1994/p/10151722.html