2013-12-14 66 views
0

我有2種方法。比較Hibernate中兩個對象的問題

@Service 
@Transactional 
public class MyService { 

    void myMethod() { 
     Entity e1 = dao.get(1); 
     e1.setName("NEW ENTITY NAME"); 
     save(e1); 
    } 

    void save(Entity e) { 
     Entity oldEntity = dao.get(1); 
     oldEntity.getName().equals(e.getName()) // TRUE. Why? 
    } 

} 

但在方法save實體不是不同,即兩個老的和更新的實體具有相同的字段值("NEW ENTITY NAME")。 Spring中的事務配置正確,默認傳播爲Propagation.REQUIRED

回答

2

看到這個answer也證實了這一點,這其實是很正常的行爲。第一個dao.get(1)檢索帶有數據庫密鑰1的實體並附加到會話中。

當執行第二個dao.get(1)時,會話仍處於打開狀態,因此Hibernate將不會再次查詢數據庫,但會返回已連接到會話的引用。

從Hibernate的角度來看,這個表只能有一個數據庫對象,並且它已經擁有對它的最新內存版本的引用,所以Hibernate不妨將它返回並備用一個查詢。

爲了將內存中的持久對象與其數據庫版本進行比較,一種方法是首先加載對象並在對對象調用setter之前進行比較。

另一種方法是首先使用session.evict()從會話中分離對象,然後從數據庫加載對象。

這將確保將數據庫的數據庫版本加載到會話中。然後可以在現在分離的驅逐對象和新加載的對象之間進行比較。

如果您不想用較新的數據替換數據庫版本,請在被驅逐的對象上調用session.merge()。

1

如果我沒有記錯的話,Hibernate在會話級別有一個緩存系統,如果一個實體被檢索到,它將被緩存並返回給同一個實例中同一實體的任何請求。因此你在比較同一個對象。您可以通過執行

oldEntity == e 

What are First and Second Level caching in Hibernate?

0

如果要更換較新的數據的數據庫版本,然後調用session.merge()被驅逐的對象

+0

這應該是評論 – ketan