又称为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的几个方法.
下面用代码演示一下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对象,再次查询时会去访问数据库,来看一下控制台打印结果是否是这样的:
果真如此,跟咱们料想的同样.