今天碰到个bug,虽然小,但是有点意思
背景是SpringMVC + Mybatis的一个项目,mapper文件里写了一条sql 大概相当于 select a from tableA where b = "123" 这样的级别
然后不管传进去的是什么 数据库里有没有 都会返回null
第一反应是sql语句写错了,比如把1和小写L弄混了之类的,传给sql的参数里有奇怪的空格等等
于是打开debug log 拿到传给sql的preparedStatement 和对应的参数
复制到console里自己查了一下,可以执行,返回结果也正确,说明不是sql的问题
既然不是sql的问题,那只好调试一下代码了
既然preparedStatement sql能够被打印出来,所以就不从业务逻辑加断点了,直接定位到PreparedStatement类 找到execute方法,上个断点开始单步
单步的时候发现ide提示说源代码和class文件对应行不一致,并且对我正在监视的变量报了一个类中不存在该变量的错
所以怀疑是引用冲突了
接下来确认一下是不是引用了奇怪的类 ,用下面这个方法去定位一下PreparedStatement的位置
public static String where(final Class cls) {
if (cls == null)throw new IllegalArgumentException("null input: cls");
URL result = null;
final String clsAsResource = cls.getName().replace('.', '/').concat(".class");
final ProtectionDomain pd = cls.getProtectionDomain();
if (pd != null) {
final CodeSource cs = pd.getCodeSource();
if (cs != null) result = cs.getLocation();
if (result != null) {
if ("file".equals(result.getProtocol())) {
try {
if (result.toExternalForm().endsWith(".jar") ||
result.toExternalForm().endsWith(".zip"))
result = new URL("jar:".concat(result.toExternalForm())
.concat("!/").concat(clsAsResource));
else if (new File(result.getFile()).isDirectory())
result = new URL(result, clsAsResource);
}
catch (MalformedURLException ignore) {}
}
}
}
if (result == null) {
final ClassLoader clsLoader = cls.getClassLoader();
result = clsLoader != null ?
clsLoader.getResource(clsAsResource) :
ClassLoader.getSystemResource(clsAsResource);
}
return result.toString();
}
用where方法去查一下类,发现jvm没有加载我认为的msql-java-connector-5.1.63 而是加载了一个内部类库里的java-connector,定位进去看了一下 确实是写的有问题,原因找到了。
最后到maven依赖里,打开依赖树,找到了加载这个自定义connector的pom条目,配置了<exclusions> ,然后重启项目,解决。