天天看点

四、MySql+Mybatis+Druid:报sql injection violation, multi-statement not allow异常

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

<update id="synchronizedNumber" parameterType="Date">
        <if test="lastUpdateTime == null">
            UPDATE business b,(SELECT business_id,num FROM orders WHERE createDate<=#{currentTime})o
            SET b.number=b.number + o.num WHERE b.id=o.business_id
        </if>
        <if test="lastUpdateTime != null">
        UPDATE business b,(SELECT business_id,num FROM orders WHERE createDate>#{lastUpdateTime} AND createDate<=#{currentTime})o
        SET b.number=b.number + o.num WHERE b.id=o.business_id
        </if>
    </update>      

  结果报错:

Caused by: java.sql.SQLException: sql injection violation, multi-statement not allow : ****
    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的服务器。

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

<property name="proxyFilters">
            <list>
                <ref bean="logFilter"/>
                <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参数就可以了。

  但是,执行之后,结果还是同样的错误!!!

  后来多方查询资料,才知道Druid配置的时候还有一个大坑就是,不要同时配置filters和proxyFilters,filter都是内置的,想通过proxyFilters来定制的话,就不要配置filters。

  我就同时在filters和proxyFilters配置“WallFilter”对象:

//其中配置文件中druid.filters=wall,stat
<property name="filters" value="${druid.filters}"/>
        <property name="proxyFilters">
            <list>
                <ref bean="logFilter"/>
                <ref bean="wall-filter"/>
            </list>
        </property>