? ?session接口是hibernate重要的組成,session接口的實現中包含一系列java集合,這些集合構成了session緩存,只要session對象沒有結束生命周期,而且沒有清理緩存,那么存放在緩存中的對象也不會結束生命周期。該session緩存可減少應用程序訪問數據庫的次數,從而一定程度上提高效率。
例1:
public void testSessionCache() {
try {
News news = (News) session.get(News.class, 1);
System.out.println(news);
System.out.println("###########執行兩次get操作,若是取的對象一樣,那么第二次從session緩存中獲取#################################");
News news2 = (News) session.get(News.class, 1);
System.out.println(news2);
以上代碼僅僅執行一次select語句,news2是在緩存中提取。第一次查詢之后得到一個News對象,將這個引用傳遞給了news,同時也傳遞給了session緩存,再次查詢的時候首先在緩存中查看是否存在news對象,若是有那么就不再從數據庫獲取,而是直接獲取session緩存的news對象。
session緩存又叫做一級緩存。對session緩存的操作有三個方法:
flush():該方法由session指向數據庫,執行該方法的時候會檢查緩存中的對象狀態跟數據庫中(讀取的)的對象狀態(或者緩存中最初的對象)是否一致,若是不一致會觸發SQL操作(update or delete等)但是數據沒有改變的話,是不會發送SQL修改語句的。
@Test
public void sessionFlush() {
News news = (News) session.get(News.class, 1);
news.setAuthor("Oracle");
}
執行該測試代碼之后,會在select語句后面出現update語句,我們可以理解,當查詢出news對象之后,存在于session 緩存中,我們使用set方法使得該 session緩存中的對象的author屬性發生了變化,所以在事務提交之前,會調用flush()「通過單步調試發現在執行set()方法的時候,沒有發送update語句,在執行事務提交的過程中,首先會flush(),執行flush()之后發送語句,但是數據沒有更改,再繼續執行commit之后,數據庫發生變化」以保持數據庫中的數據跟session緩存中的一致。(注意,可以在獲取一個對象之后,然后立即(但不提交)修改某個屬性,此時打印出來的,一個是從數據庫中取得的屬性,另一個是剛set的屬性值,因為都是在緩存中,所以首先獲取到的是緩存中的數據)。
flush可能會發送SQL語句但是不會提交事務,此時數據庫中的數據不會發生改變。需要提交事務才會改變。
在沒有提交事務或者沒有顯示調用flush之前,也有可能進行flush操作(1.執行HQL或者QBC查詢的時候,會先進行flush,以保證得到數據表的最新記錄。2若記錄的ID生成策略是由底層數據庫使用自增方式native方式生成的,那么在調用save()方法后會立即發生SQL語句,因為save方法后必須保證對象的ID存在,但是若是ID由hibernate提供,則在執行commit()之后才會生成SQL語句)。
refresh():有數據庫指向緩存,強制使緩存中的數據跟數據庫保持一致,也就是強制發送一條select語句。
@Test
public void testRefresh() {
News news = (News) session.get(News.class, 4);
System.out.println(news);
session.refresh(news);//執行之后便會發送select語句,下面的打印是否是運行中修改的最新數據,還需要注意hibernate的事務隔離級別。
設置<property name="hibernate.connection.isolation">2</property>即可完成該效果
System.out.println(news);
}