解決JPA查詢到的對象屬性被set後,自動執行update

問題描述

做項目開發的時候遇到這樣一個問題:更新數據庫某一記錄的時候,先從數據庫中查詢到這個紀錄,然後set修改數據項,當某個字段set和查詢出來的不一致的時候,看到控制檯打印的SQL日誌顯示執行了Update操作,很納悶,查看代碼,只是一個簡單的set操作啊,數據庫怎麼會被更新?
查看資料後才知道,使用JPA查詢後的對象處於持久態,持久態的對象屬性在被set後,會自動執行update語句更新數據庫。
這才恍然大悟,基於這個原因,只要把持久態的對象轉換爲遊離態或者是臨時態,就可以解決問題。
先理解下Hibernate 中對象的三種狀態:

  1. 臨時狀態:通過new新建的對象,沒有被持久化,也不在session緩存中

  2. 遊離狀態:已經被持久化,但不在session緩存中

  3. 持久狀態:已經被持久化,也在session緩存中

(持久化:數據庫有這條數據)
持久態到遊離態的方法有:session.close()、session.evict(obj)、session.clear()

  1. close():關閉session,整個session中的持久態對象都成爲遊離態
  2. clear():清楚session中的所有緩存,所有持久化對象變爲遊離態
  3. evict(obj):把某個持久化狀態的對象從session中清除,該對象變爲遊離態,推薦用此方法

解決方案

  1. 隔離Entity:new一個對象,把查詢出來的對象通過BeanUtils.copyProperties賦值給new出來的對象,更新操作使用new之後的對象

  2. 把持久化狀態的obj從session中清除

    1. 首先引入EntityManager
    @PersistenceContext
    private EntityManager entityManager;
    
    1. 把obj從session中清除
    HibernateEntityManager hibernateEntityManager = (HibernateEntityManager) entityManager;
    Session session = hibernateEntityManager.getSession();
    session.evict(obj);
    

總結

出現這種現象的前提,查詢以及對查詢後的實體set值都必須在一個事務裏,並且在方法執行結束,事務提交前,不管有沒有顯示調用Update,JPA都會自動調用Update

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章