上一節,我們實現了用戶列表查詢,已經按條件精確查詢:
if(student.getUsername() != null && !"".equals(student.getUsername())){
sql += " and username = ?";
args.add(student.getUsername());
}
if(student.getName() != null && !"".equals(student.getName())){
sql += " and name = ?";
args.add(student.getName());
}
因為是精確查詢,所以我們使用了等號,如果是模糊查詢咋辦呢?在sql語句里需要使用like關鍵字,第一次修改:
if(student.getUsername() != null && !"".equals(student.getUsername())){
sql += " and username like '%?%'";
args.add(student.getUsername());
}
if(student.getName() != null && !"".equals(student.getName())){
sql += " and name like '%?%'";
args.add(student.getName());
}
從代碼上看,貌似沒有啥問題。ok,來測試一下。
結果報錯了:
出現問題不要怕,用調試工具來一步一步調,走進源碼里進行調試:
進入這個方法:
走到這個queryForLong方法,再進去:
發現又調用了queryForString方法,ok,繼續走進去:
sql:
select count(1) from (select * from t_student where 1=1 and name = '%?%') t
objects:
[皮]
再去看一下queryForJsonObject方法:
我的天,又調用了queryForMap方法。。
queryForMap中,最終還是調用了queryForList方法,至於第一句話,是反編譯出來的。這一點可以看出我之前寫的源碼是存在問題的,創建了一個Map對象但是最終沒有用到。好吧,不用在意這些細節。我估計當初寫源碼的時候,那個Map本來是想要去返回的,可實際上 list.get(0)返回的就已經是一個Map對象了,所以我實際上不需要去new一個HashMap。
我們再走入queryForList方法,發現在這一行報錯了:
終於找到問題了,就是在這個setObject的過程中,出了問題。這是原生的jdbc方法。
其實,這是jdbc內部的一個問題,再回過來看一下sql語句:
select count(1) from (select * from t_student where 1=1 and name = '%?%') t
?是不能放在單引號里面的,如果放在單引號里面,PreparedStatement並不視它為一個參數,錯就錯在這。
看到這里,有的人就要問了,那我如何才可以實現模糊查詢呢?既然jdbc不允許我們把?寫在單引號里面,那么我們干脆就寫一個問號,沒有單引號不就行了?
修改sql為:
select count(1) from (select * from t_student where 1=1 and name = ?) t
然后把%拼接進去:
if(student.getUsername() != null && !"".equals(student.getUsername())){
sql += " and username like ?";
args.add("%" + student.getUsername() + "%");
}
if(student.getName() != null && !"".equals(student.getName())){
sql += " and name like ?";
args.add("%" + student.getName() + "%");
}
結果:
這樣就實現了一個模糊查詢。相信很多jdbc初學者,在進行模糊查詢的時候,都曾經踩過這個坑,再強調一遍:?是不能放在單引號里面的,如果放在單引號里面,PreparedStatement並不視它為一個參數。
您的支持是我寫作的最大動力: