這個問題令我真的是印象深刻。現在記錄一下該問題的詳細解決過程,解決問題的思路很重要。
1.問題描述:
一個簡單的查詢,根據某字段查詢值,實體類是一個視圖。
dao:
@Query(value="from ViewGxxx where num = ?1")
VietEntity findByunt1(String ccount);
查詢:
ViewDebtEntity en1 = viewDao.findByAccount1(dkzhList.get(1));
ViewDebtEntity en2 = viewDao.findByAccount1(dkzhList.get(0));
ViewDebtEntity en3 = viewDao.findBytAccount1("021001055215000000790");
三個查詢條件是不相同的。
查詢結果以及現象如下:
- 所有的值都相同,en1 = en2 = en3
- 比如第一次查的結果爲“xxx” , 那之後多次查詢的結果都爲“xxx” ,儘管查詢條件都不一樣。
2.問題解決
開始用的是 根據方法名查詢的 如 findbyxxxIn(List) , 就是參數是一個list , 批量查詢,
出現問題後,以爲是方法的問題,後來就改爲上述的直接用jpql 語句查詢。然後問題依舊存在。
- debug調試,查看查詢方法的輸入參數,確實不一樣。
- 用上述幾個不同的參數去數據庫寫sql 查詢,確實能查到不同的數據。
- 改變日誌數據,查看spring data jpa 發送的sql 打印,看到三次打印的sql , 一模一樣但是參數卻是個 “?” 。
- 改變日誌輸出配置,讓sql 的參數也顯示出來。具體做法
- sql 參數也打印了出來,結果發現,發送的sql的參數也的確是不同的。
進行到這裏就真的感到這個問題妖異的很了。
接下來進行進一步分析。
什麼原因能導致這樣的現象呢, 想想看,同樣的sql 語句,不同的參數,查詢出來的結果都一樣,並且都等於第一次查詢的。
那就難免想到緩存的東西了,問題是這種緩存明顯是不合邏輯也不合常理的。
最後去看了實例類(orm 數據裏邊是view)
注意這裏將id 視爲主鍵 (邏輯上不允許重複的)
然後去數據庫一探究竟:
看到一個id的字段,值卻都是相同的. 這…
然後帶着這個證據去分析上述的問題:
- 我是將id屬性用@Id 作爲主鍵, 那麼 sping data jpa 就認爲id 屬性是唯一的.
- 然後我進行第一次查詢,得到 en1, 得到的結果爲 xxx (id 爲1) sping data jpa 底層實現用的hibernate 發送sql 進行查詢,.
- 然後進行第二次查詢,然後發送sql , 數據庫的索引機制,查找普通字段,會先找到對應id , 然後,有id ,查詢對應的整個記錄. 由於 第二次查詢雖然用的不同條件,但是對應的id相同,於是從緩存中返回了上次相同id的查詢結果.
因此這個視圖的數據是有問題的了,id 都一樣, 爲了證實這一點,我再視圖裏邊找了一個唯一的字段,響應的在其上邊加上@Id註解, 再進行查詢得到的結果就是不同的了.