解決JPA對查詢對象set屬性值導致數據更新的問題


問題描述

1、開啟了數據庫事務

2、通過EntityManager執行查詢,獲得返回對象

3、代碼業務邏輯處理,其中有對象set屬性值的操作

4、沒有執行過JPA的save方法或者update語句

5、提交數據庫事務,發現數據庫中對應的數據更新成了新的屬性值

問題復現

 

@Transactional
@Override
public void selectAndFlush(String id) {
   User user = crudDao.selectByPrimaryKey(id);
   user.setName("testFlushNotUpdateDB");
}

 

Hibernate: selectuser0_.AGE as AGE8_0_, user0_.CARD as CARD9_0_, user0_.NAME as NAME10_0_, user0_.PRICE as PRICE11_0_ from USER user0_ where user0_.ID=?

Hibernate: update USER set AGE=?, CARD=?, NAME=?, PRICE=? where ID=?

可以看到在set方法之后JPA自動幫我們執行了update操作

問題原因

根本原因是因為我們在執行查詢以后,查詢結果對象在EntityManager上下文中進行了一級緩存,執行set方法以后緩存對象狀態【持久態】,事務提交時會自動幫我們flush到數據庫中,導致數據被更新,下圖為一級緩存對象:

 

 解決方法

這里提供4中解決方法:

1、提交事務之前執行EntityManager.clear()方法,清理緩存對象

2、業務代碼在不需要更新數據時避免直接對查詢對象進行set操作,可以使用BeanUtils.copyProperties()方法復制對象,再進行set操作

3、使用EntityManager.evict()方法清理指定對象

4、修改JPA的FlushMode,沒有測試過,理論可行,代碼如下:

 

((Session) getEntityManager().getDelegate()).setFlushMode(FlushMode.MANUAL);

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM