避免 Hibernate 中用get/load方法獲取的實體呼叫set方法後自動更新
1、問題症狀描述
最近在處理一個新需求問題,程式碼的大致邏輯是獲取一個實體物件,呼叫該物件的set方法設定其中的某些欄位,然後把修改後的實體作為引數供其他地方呼叫,根據返回值來決定是否更新這個實體到資料庫中。
按照這個思路呼叫了系統中的getByid方法,結果測試的時候發現,不管返回值是什麼,這個實體最終都被更新到資料庫中了。好吧,這明顯是有問題的....【沒有問題的程式碼不是好程式碼 - -|| 】
2、問題原因分析和解決辦法
2.1 檢視日誌資訊後發現,系統總是會列印出一個update語句。說明系統的確是執行了更新操作的,但是我並沒有呼叫任何和update相關的方法。
2.2 跟蹤程式碼發現,getById方法其實是呼叫了hibernate的get方法。嗯,果然,問題出在這裡了.....
2.3 Hibernate的get和load方法查詢出的實體都是持久化物件,拿到該物件後,如果你呼叫了該物件的set方法,那麼在事務遞交的時候,Hibernate會把你設定的值自動更新到資料庫中。
解決辦法:
在獲取實體物件後,呼叫下getHibernateTemplate().evict(entity)方法,該方法的作用是把持久化物件變成託管狀態。變成託管狀態後,Hibernate就不會再去自動更新該實體。
3、相關知識擴充套件
Hibernate的幾種實體狀態:
1.瞬態:
一個實體通過new操作符建立後,沒有和Hibernate的Session建立關係,也沒有手動賦值過該實體的持久化標識(持久化標識可以認為是對映表的主鍵)。
此時該實體中任何屬性的更新都不會反映到資料庫表中。
2.持久化:
當一個實體和Hibernate的Session建立了關係,並獲取了持久化標識,而且在Hibernate的Session生命週期記憶體在。
此時針對該實體任何屬性的更改都會直接影響到資料庫表中一條記錄對應欄位的更新,即與資料庫表同步。
3.脫管:
當一個實體和Hibernate的Session建立了關係,並獲取了持久化標識,而此時Hibernate的Session生命週期結束,實體的持久化標識沒有被改動過。
針對該實體任何屬性的修改都不會及時反映到資料庫表中。
關閉session可以使實體從持久化狀態轉為託管狀態。
知識擴充套件部分參考自 http://blog.csdn.net/sunhuwh/article/details/9183539 ,感謝作者。
轉帖請註明文章來源: http://blog.csdn.net/yang_lover/article/details/45057181
相關文章
- java反射呼叫set和get方法的通用類Java反射
- Bean類自動生成判斷null值的Set()和Get()方法BeanNull
- 快速生成get、set方法
- idea中引入lombok外掛後編譯時實體bean無get/set方法IdeaLombok編譯Bean
- postman自動呼叫獲取tokenPostman
- +load和+initialize方法呼叫時機
- Hibernate查詢自動更新
- Idea實體類上加@Data註解但get/set方法不生效Idea
- Hibernate/JPA中避免save()冗餘呼叫
- 證明:ThreadLocal的get,set方法無法防止記憶體洩漏thread記憶體
- 封裝中的get、set方法-學習筆記封裝筆記
- 呼叫API介面獲取淘寶商品評論:方法與實戰API
- 獲取方法
- Qt中用C++呼叫Python檔案的三種方法QTC++Python
- 介面自動化測試框架--http請求的get、post方法的實現框架HTTP
- Win10 1909系統關閉自動更新後自動開啟的解決方法Win10
- IDEA不使用lombok,如何快速生成get和set方法IdeaLombok
- 用Certbot 獲取和自動更新SSL證書
- 09 獲取需求的方法
- 前端 | Vue nextTick 獲取更新後的 DOM前端Vue
- 帝國cms內容頁圖片自動獲取alt和title的方法
- 獲取爬蟲動態IP的三種方法爬蟲
- lombok get/set 與 JavaBean get/setLombokJavaBean
- 【JavaSE】淺談TreadLocal,TreadLocal的常用方法set()、get()、remove()原始碼分析JavaREM原始碼
- CodeIgniter3 獲取GET/POST/PUT/DELETE方法多種方式傳參delete
- win10系統設定更新後不提示自動重啟的方法Win10
- golang呼叫模組程式實現互動輸入自動化,獲取imei及iccidGolang
- 使用JPA和Hibernate呼叫儲存過程的最佳方法 - Vlad Mihalcea儲存過程
- 如何禁用win10自動更新驅動_win10關閉驅動自動更新的方法Win10
- PHP --反射 --獲取類的方法PHP反射
- 獲取類名稱的方法
- WPS自動更新怎麼關閉? 詳解WPS自動更新的關閉方法步驟
- windows10 自動更新怎麼關閉_關閉windows10 自動更新的方法Windows
- 將一個物件多次放入set不呼叫equals方法物件
- win10停止自動更新操作 win10停止自動更新方法Win10
- initialize方法與load方法比較
- NSObject 的 initialize 和 load 方法Object
- jQuery – AJAX load() 方法jQuery
- 三種方法實現:獲取 url 中的引數