1. 程式人生 > >Hibernate的FlushMode與session.flush()

Hibernate的FlushMode與session.flush()

原文出處:https://blog.csdn.net/aitangyong/article/details/50483743

 

我們藉助於Session來操作資料庫,Session是有快取的(在hibernate中稱為一級快取),當我們呼叫session.save()或者update()等的方法的時候,hibernate並不一定會馬上將修改同步到資料庫,而是先將這些資訊儲存在session快取中,由hibernate自己在合適的時候將快取中的資料,同步重新整理到資料庫中。正是由於hibernate的這種快取機制,在同一個session中多次修改一個記錄,最終只會向資料庫發出一條update語句。由於session快取以及髒資料檢查機制,能夠幫助我們儘可能少地發出SQL語句。

 

hibernate提供了FlushMode介面,能夠讓我們干預hibernate將髒資料同步到資料庫的時機。Session.flush()會觸發hibernate將資料同步到資料庫。可以通過session.setFlushMode()來修改重新整理模式。FlushMode提供了4種快取模式:MANUAL、COMMIT、AUTO和ALWAYS。

 

MANUAL:我們必須在程式碼中手動呼叫session.flush(),hibernate才會將髒資料同步到資料庫。如果我們忘記了手動重新整理,那麼就算是通過session.getTransaction().commit()提交了事務,也不能將修改同步到資料庫。

Session session = sessionFactory.openSession();
session.setFlushMode(FlushMode.MANUAL);
 
.....
 
session.flush();//切記不能遺忘
session.getTransaction().commit();
session.close();

 

COMMIT:當資料庫事務提交的時候會重新整理快取,當然手動呼叫flush()肯定也是可以的,不過沒有必要罷了。

Session session = sessionFactory.openSession();
session.setFlushMode(FlushMode.COMMIT);
 
.....
 
session.getTransaction().commit();
session.close();

AUTO:The Session is sometimes flushed before query execution in order to ensure that queries never return stale state. This is the default flush mode. 事務提交或者手動重新整理,都能將髒資料同步到資料庫。除此之外,某些查詢出現的時候也會導致快取重新整理。

 

ALWAYS:The Session is flushed before every query. This is almost always unnecessary and inefficient. 只要有查詢出現,或者事務提交,或者手動重新整理,都會導致快取重新整理。這個策略效能比較差,實際中不會使用。

 

hibernate預設的重新整理模式是AUTO,但是這個策略並不合理, 實際中也不會用到。

public void testFifferenceBetweenAutoAndAlways() {
	Session session = sessionFactory.openSession();
	session.setFlushMode(FlushMode.AUTO);
	session.beginTransaction();
 
	Student student = new Student();
	student.setId(1);
	student.setAge(100000);
 
	session.update(student);
 
	System.out.println("after save");
 
	Query query = session.createQuery("from Student where id =2");
	System.out.println(query.list().get(0));
 
	System.out.println("after query");
 
	session.getTransaction().commit();
	session.close();
}

這段程式碼我們設定的是AUTO,程式碼中出現了一次查詢,按道理來說這次查詢並不需要將update操作同步到資料庫。但是實際上執行結果如下:

 

可以看到AUTO並沒有我們想象中的那麼智慧,stackoverflow上這篇文章也列出了AUTO一些不好的地方。

1.you don't control when Hibernate will decide to execute UPDATE/INSERT/DELETE.

2.potential performance issues because every object modification may lead to dirty checking + DML statement execution.

3.you are not taking advantage of batching and other optimizations that Hibernate can perform when it is not trying to avoid 'stale' state

 

所以最常用其實是MANUAL和COMMIT策略,如果使用了MANUAL,切記需要手動重新整理session快取。