今天碰到個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> ,然后重啟項目,解決。