共計 1219 個字符,預計需要花費 4 分鐘才能閱讀完成。
行業資訊
數據庫
如何避免 Hibernate 中用 get/load 方法獲取的實體調用 set 方法后自動更新
如何避免 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 可以使實體從持久化狀態轉為托管狀態。
看完上述內容,你們掌握如何避免 Hibernate 中用 get/load 方法獲取的實體調用 set 方法后自動更新的方法了嗎?如果還想學到更多技能或想了解更多相關內容,歡迎關注丸趣 TV 行業資訊頻道,感謝各位的閱讀!