開發中遇到乙個問題,網上有人描述問題,但是沒有找到答案,自己看了ibatis原始碼才明白過來
執行sql:
丟擲如下異常:
先描述一下場景:
訂單和機票表是一對多的關係,這條語句是根據機票表中的一些條件和訂單中的條件進行分頁查詢的語句,這裡是統計總數。
由於機票表很少查詢,所以dba要求沒有查詢機票表的時候就不要關聯機票表,並不需要distinct關鍵字。於是就出現了下面這條動態sql語句,先不管這條語句是否**,我說說明的問題是,這條語句在上線執行是會出問題的(單元測試不會有任何問題),為什麼呢?答案源自於sqlmap的自身的乙個處理方式。
sqlmap在執行這條sql的時候會根據orders.searchorderlistconut這個key來查詢select返回的列表字段,如果沒有找到,就會分析這條sql,然後使用orders.searchorderlistconut做為key,selelect中返回的字段列表作為value快取起來備用(問題就是在這裡),以後每次查詢這條searchorderlistconut語句的時候,就會直接從快取中拿出返回字段。假設這條語句先執行了select count(o.id) from et_orders o.....,那麼這裡快取起來的字段就是count(o.id),而第二次查詢時假設查詢了機票表中的資訊,那麼就需要時select count(distinct o.id) from et_orders o..... ,這時,ibatis使用快取起來的count(o.id) 作為欄位名來取,當然就會取不到值,從而丟擲乙個異常。
ibaits中快取列名的地方在這裡:
public synchronized object getresults(statementscope statementscope, resultset rs)
throws sqlexception
return super.getresults(statementscope, rs);
} 知道了這個原因,那麼問題就可以解決了。既然是根據select 的id快取了欄位名,那麼就可以從這裡下手了,先不管方法優劣,解決辦法如下:
1:既然快取了,那麼第乙個方法就是去掉這個快取。(這個能解決問題,但是不好,又麻煩,又影響效能),之所以單元測試沒有發現這個問題,就是因為,單元測試是跑一次就停下來了,再跑第二次,所以這個快取相當於沒有。
2:給這個動態變化的字段增加乙個別名,例如
select count(distinct o.id)
num這樣快取中就會留下num別名作為欄位名,至於前面如何變化,ibatis不管
3:自然就是sql語句拆分,將要關聯機票表和不關聯機票的sql語句分開,就不會存在這個問題了。
Ibatis快取select欄位名引起的問題
開發中遇到乙個問題,網上有人描述問題,但是沒有找到答案,自己看了ibatis原始碼才明白過來 執行sql select count distinct o.id from et orders o tickets ticket 這裡省略 丟擲如下異常 先描述一下場景 訂單和機票表是一對多的關係,這條語句...
Ibatis快取select欄位名引起的問題
開發中遇到乙個問題,網上有人描述問題,但是沒有找到答案,自己看了ibatis原始碼才明白過來 執行sql select count distinct o.id from et orders o tickets ticket 這裡省略 丟擲如下異常 先描述一下場景 訂單和機票表是一對多的關係,這條語句...
Ibatis快取設定
cachemodel id cache logic columns type memory readonly true serialize false flushinterval hours 24 property name reference type value strong cachemode...