【转载】MySql+Mybatis+Druid在一个Mybatis中执行多条SQL 有更新!

  zyw090111

    做一个批量update的操作 ,sqlmap如下:

    <update id="updateBatch" parameterType="java.util.List">  
      <foreach collection="list" item="item" index="index" open="" close="" separator=";">  
        update device_bd_token   
    	 <set>  
    	   access_token=#{item.accessToken}  
    	 <set>  
        where device_id = #{item.deviceId}  
      <foreach>  
    <update>
    

    在不设置的情况下会报错:

    Caused by: java.sql.SQLException: sql injection violation, multi-statement not allow : update device_bd_token 
                     SET access_token=? 
                    where device_id = ?
              ; 
                    update device_bd_token 
                     SET access_token=? 
                    where device_id = ?
    	at com.alibaba.druid.wall.WallFilter.check(WallFilter.java:714)
    	at com.alibaba.druid.wall.WallFilter.connection_prepareStatement(WallFilter.java:240)
    	at com.alibaba.druid.filter.FilterChainImpl.connection_prepareStatement(FilterChainImpl.java:448)
    	at com.alibaba.druid.filter.FilterAdapter.connection_prepareStatement(FilterAdapter.java:928)
    	at com.alibaba.druid.filter.FilterEventAdapter.connection_prepareStatement(FilterEventAdapter.java:122)
    	at com.alibaba.druid.filter.FilterChainImpl.connection_prepareStatement(FilterChainImpl.java:448)
    	at com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl.prepareStatement(ConnectionProxyImpl.java:342)
    	at com.alibaba.druid.pool.DruidPooledConnection.prepareStatement(DruidPooledConnection.java:318)
    

    刚开始以为是连接数据库的url上没有加上支持批量的参数,然后就改了下:

    jdbc.url=jdbc:mysql://192.168.11.107:3306/alarm_db?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8
    

    结果还是同样的错误!但是在命令行直接执行又是没问题的,这就很奇怪了!

    仔细看日志,好像是Druid的WallFilter.check()抛出来的,那就是说是Druid在做预编译的时候,给抛出的异常,还没有到mysql的服务器。

    最终的解决办法是这样的:

    <bean id="dataSourceOne" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
      <property name="proxyFilters">
    	  <list>
    		  <ref bean="stat-filter" />
    		  <ref bean="wall-filter"/>
    	  </list>
      </property>
    </bean>
    
    <bean id="wall-filter" class="com.alibaba.druid.wall.WallFilter">
    	<property name="config" ref="wall-config" />
    </bean>
    
    <bean id="wall-config" class="com.alibaba.druid.wall.WallConfig">
    	<property name="multiStatementAllow" value="true" />
    </bean>
    

    配置一个multiStatementAllow参数就可以了。

    看下源码的处理:
    fee826845e9c4c0989cb478ef89ab1bc-20160128134204469.png
    0451b45389d348f98df5850a950f196b-20160128134256648.png
    20b2f6e5b80c4e9fba3ee587f22c8532-20160128134444760.png

    也就是说,只要把config的multiStatementAllow设置为true就可以避免出现这样的错误了!
    Druid配置的时候还有一个大坑就是,不要同时配置filters和proxyFilters,filter都是内置的,想通过proxyFilters来定制的话,就不要配置filters。

    DruidDataSource继承了DruidAbstractDataSource,
    474891d9520e415f9f5ec83a999c1363-20160128135016408.png

    可以看出来,既可以配置filters,也可以配置proxyFilters,不同的是,filters是字符串别名,proxyFilters是类。

    我们继续看一下这些字符串的值应该是啥样的:
    807e9e6473a4476eadd22c31ad616610-20160128135406254.png
    74a75c774bff4ffea4c4049af612f554-20160128135452086.png
    0e8d5d3657534513a78a06658a0aebf9-20160128135538505.png
    d1cf5db699e1489d925b0922f966bdc8-20160128135725840.png

    原来在这里:
    4edd5e0ca4184fdba131495766706ef6-20160128135837748.png
    这就是druid内置的所有的filter了,去掉前缀druid.filters就是别名了。

    原文链接 http://blog.csdn.net/goldenfish1919/article/details/50600053