由于一些原因,我需要通过接口做个sql查询的功能。
通过mybatis的注解来实现,传入任意查询sql,返回结果
@Select("${sql}")
List<Map<String,Object>> commonSelect(@Param("sql")String sql);
为了防止sql有update和insert之类的操作,使用了Druid连接池的过滤功能,让sql变成只读操作,项目本身数据源使用了sharding-jdbc做分表处理
<bean id="wall-filter-config" class="com.alibaba.druid.wall.WallConfig" init-method="init">
<!-- 指定配置装载的目录 只读数据源-->
<property name="dir" value="META-INF/druid/wall/mysql" />
<property name="selectIntoAllow" value="false" />
<property name="deleteAllow" value="false" />
<property name="updateAllow" value="false" />
<property name="insertAllow" value="false" />
<property name="mergeAllow" value="false" />
</bean>
<bean id="wall-filter" class="com.alibaba.druid.wall.WallFilter">
<property name="dbType" value="mysql" />
<property name="config" ref="wall-filter-config" />
</bean>
然后写了一个测试类,传一个update 的sql看看效果
发现程序一直在跑,没有结束,电脑cpu一下飚起来了,风扇呼呼响
猜测哪里有死循环导致的,查了半天,在GitHub找到了类型的情况
原来是在@select 的tag里面执行了update的语句,如果用了sharding-jdbc就会死循环
// org.apache.ibatis.executor.resultset.DefaultResultSetHandler.java
private ResultSetWrapper getFirstResultSet(Statement stmt) throws SQLException {
ResultSet rs = stmt.getResultSet();
while (rs == null) {
// move forward to get the first resultset in case the driver
// doesn't return the resultset as the first result (HSQLDB 2.1)
if (stmt.getMoreResults()) {
rs = stmt.getResultSet();
} else {
// Note: using sharding- JDBC, stmt.getupdatecount () is always greater than 1 (resulting in an infinite loop),
// But using mysql's native driver returns -1
if (stmt.getUpdateCount() == -1) {
// no more results. Must be no resultset
break;
}
}
}
return rs != null ? new ResultSetWrapper(rs, configuration) : null;
}
注意这段话
Note: using sharding- JDBC, stmt.getupdatecount () is always greater than 1 (resulting in an infinite loop)
高版本的包已经解决了这个问题
问题导航:
https://github.com/apache/incubator-shardingsphere/issues/1603