2500-使用MyBatis操作MySQL進行批量更新的注意事項
阿新 • • 發佈:2018-12-20
原則上一條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. 資料庫連線加引數
新增引數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>