hibernate筆記--緩存機制之 一級緩存(session緩存)

一級緩存:

  又稱爲session緩存,它和session生命週期相同,週期很是短.是事務級別的緩存:sql

  仍是以Book和Category這兩個表爲例,咱們用代碼觀察一個緩存的存在:數據庫

假設如今我要去查詢id=1的Book信息:緩存

        List<Book> list =(List) session.createQuery("from Book").list(); System.out.println(list.get(0).getName()); Book book = (Book)session.get(Book.class, 1); System.out.println(book.getName());        

我這裏先查詢了全部的Book,打印出了index=0,即id=1的那本書的書名,接着用get方法再次獲取了id=1的Book,咱們看一下控制檯的打印信息:session

  經過打印信息咱們能發現一個現象,當第二次咱們使用get(..)方法去查詢時,咱們如願獲得了書名,但卻沒有select語句,說明了什麼問題?說明了使用get()方法獲取id=1的Book時,hibernate並無去訪問數據庫,而是在某一個地方就獲得了這個id=1的Book的信息,不難發現,咱們第一次使用createQuery()時,其實已經獲得了這條Book的信息,而hibernate將這些信息放到了一個緩存裏,當執行查詢語句時,hibernate沒有着急的當即訪問數據庫去查詢,而是先到這個緩存裏去找找有沒有他所要查詢的數據,若是有的話,那就皆大歡喜了,不須要訪問數據庫,提升了效率,而這個緩存.就是咱們所說的一級緩存,也叫session緩存.測試

  同時咱們也能知道,get方法使用了一級緩存,用get查詢數據時,首先檢查緩存中是否有該數據,若是有,直接從緩存中獲取該數據直接返回,若是沒有,再去訪問數據庫查找.load也支持一級緩存,可是同時load同時也支持延遲加載.要注意.spa

  接下繼續測試代碼:hibernate

List<Book> list =(List) session.createQuery("from Book").list(); System.out.println(list.get(0).getName()); list =(List) session.createQuery("from Book").list(); System.out.println(list.get(0).getName())

在代碼中,咱們執行了兩次session.createQuery(),若是隻打印一條sql語句,說明list查詢也支持一級緩存,打印結果是這樣:code

很不幸,控制檯打印出了兩條sql語句,這就說明了:對象

  list查詢不支持一級緩存,但list查詢會把返回的結果保存到session緩存,同理uniqueResult()查詢也是如此.blog

接下來繼續測試:

List<Book> list =(List) session.createQuery("from Book").list(); System.out.println(list.get(0).getName()); Iterator<Book> iter = session.createQuery("from Book").iterate(); while(iter.hasNext()){ System.out.println(iter.next().getName()); }

這裏咱們第一次使用list查詢獲得全部Book信息,而後用iterate查詢,獲得一個包含全部Book的迭代器集合,那麼他會不會支持一級緩存,這是控制檯打印的信息:

  乍一看,第二次查詢的時候依然打出了sql語句,看來iterate查詢是不會先去session中查找的了,可是仔細觀察第一條sql語句,能夠發現,它僅僅查詢了Book的id,但依然打印出了每本書的書名.說明了,iterate依然是在緩存中查詢的數據,因此,iterate是支持一級緩存的,一樣它執行的查詢,也會把返回結果保存到session緩存中.

` 如今再來看一下管理session的幾個方法.

  1. session.flush():通常是結合事務對象Transaction用的,用來清理緩存,執行sql,避免內存溢出,假設你要保存十萬條數據,你確定不但願當保存到九萬條的時候程序出錯,而後事務回滾,致使一條數據都沒有保存上,這時候你能夠每保存一千條數據就執行一次session.flush(),這樣的話,每保存一千條數據,就會執行到數據庫,而後清理一下session緩存.
  2. session.evict(...);從session緩存中幹掉你指定的某一個對象.
  3. session.clear():將當前session緩存中保存的全部對象通通幹掉.

下面用代碼演示一下evict,和clear方法:

     Book book =(Book) session.get(Book.class,1); System.out.println(book.getName()); session.evict(book); //b表示幹掉session中保存的全部對象,固然也包括Book對象 //session.clear()
        book =(Book) session.get(Book.class,1); System.out.println(book.getName());

按照咱們的設想,因爲執行第二次查詢以前,咱們經過session.evict(book)方法,幹掉了book對象,再次查詢時會去訪問數據庫,來看一下控制檯打印結果是否是這樣的:

果真如此,跟咱們料想的同樣.

相關文章
相關標籤/搜索