hibernate缓存(一级缓存二级缓存)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hibernate缓存(一级缓存二级缓存)相关的知识,希望对你有一定的参考价值。
一、一级缓存(Session缓存)
意义:提高hibernate查询效率。
缺点:可能会因并发,产生数据不一致。
基于session的缓存,利用hibernate执行查询的时候,hibernate会首先从session缓存去找,如果存在,则直接返回,如果不存在,则利用orm执行查询,将得到的对象保存至session缓存。
可以使用session.evict(obj);将obj从session缓存中移除。
注意:一级缓存,自动开启
hibernate一些与一级缓存相关的操作:
数据放入缓存:
1、save():当session对象调用save方法保存一个对象后,该对象会被放入到session的缓存中。
(2)、get( )和load( ):当session对象调用get( )和load( )方法从数据库中取出一个对象后,该对象也会被放入session的缓存中。
下面证明一下缓存的存在:
View Code
1 package com.it.test; 2 import org.hibernate.SessionFactory; 3 import org.hibernate.Transaction; 4 import org.hibernate.cfg.Configuration; 5 import org.hibernate.classic.Session; 6 import com.it.bean.UserInfo; 7 public class Test2 { 8 public static void main(String[] args) { 9 // TODO Auto-generated method stub 10 //创建SessionFactory 11 SessionFactory sessionfactory = null; 12 //创建session 13 Session session = null; 14 //创建事务 15 Transaction tx = null; 16 try { 17 sessionfactory = new Configuration().configure().buildSessionFactory(); 18 session = sessionfactory.getCurrentSession(); 19 //开启事务 20 tx=session.beginTransaction(); 21 UserInfo u = (UserInfo) session.get(UserInfo.class, "1001"); 22 System.out.println("-------"); 23 //清除缓存,这里如果没有清除缓存,那么控制台就会只输出一次查询,当清除了缓存后就会有输出两次查询语句。这正好说明了缓存的存在。 24 session.evict(u); 25 UserInfo u1 = (UserInfo) session.get(UserInfo.class, "1001"); 26 //提交 27 tx.commit(); 28 } catch (Exception e) { 29 e.printStackTrace(); 30 //事务回滚 31 tx.rollback(); 32 } 33 } 34 }
数据从缓存中清除:
(1)、evict( ):将指定的持久化对象从缓存中清除,释放对象所占的内存资源,指定对象从持久化状态变为脱管状态,从而成为游离对象。
(2)、clear( ):将缓存中的所有持久化对象清除,释放其占用的内存资源;
其他缓存操作:
(1)、contains( ):判断指定的对象是否存在于缓存中。
(2)、flush( ):刷新缓存区的内容,使之与数据库保持同步。
二、二级缓存(SessionFactory缓存)
基于SessionFactory 的缓存,利用hibernate执行查询的时候,hibernate会首先从session缓存去找,如果存在,则直接返回,如果不存在则去二级缓存中去找,存在则返回,不存在则利用orm执行查询,将得到的对象保存至session缓存,可以存至二级缓存。
注意:二级缓存需要在SessionFactory配置文件中,进行两处配置。
a.配置启用二级缓存
b.配置二级缓存实现类
需要对缓存本身进行专门的配置。(xxx.xml--配置缓存)
适用场合:频繁查询,海量数据,极少修改的对象。
三、延迟加载
hibernate下延迟加载:load执行查询时,返回hibernate代理对象,当操作其非主属性时才会利用orm执行。
eg:(部分代码)
View Code
1 //延迟加载--用的时候才执行 2 UserInfo u = (UserInfo) session.load(UserInfo.class, "1001"); 3 System.out.println("---1----"); 4 System.out.println(u.getUser_name()); 5 //输出结果:查询语句在------1-----后才执行,用到的时候再执行,且如果取得是主属性,就不用查询,因为load里已经给了
延迟加载可以在bean对应的xxxxx.hbm.xml文件中设置lazy="false"(关闭了延时加载,就会变成即可加载)
load和get的区别:
load get
默认:延迟加载 默认:即可加载
查不到:抛出异常 查不到:返回null
使用load需注意:操作非主属性时要在事务提交之前使用(会报错:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session);
而使用get时在提交事务后仍能操作非主属性。
View Code
1 使用load: //延迟加载--用的时候才执行 2 UserInfo u = (UserInfo) session.load(UserInfo.class, "1001"); 3 System.out.println("---1----"); 4 tx.commit(); 5 //在事务提交之后操作非主属性会抛异常:org.hibernate.LazyInitializationException 6 | System.out.println(u.getUser_name()); | 7 |--------------------------------------------------------------------------------------------------| 8 使用get: //使用get 9 UserInfo u = (UserInfo) session.load(UserInfo.class, "1001"); 10 System.out.println("---1----"); 11 tx.commit(); 12 //在事务提交之后还能操作属性,因为已经得到在之前已经得到了该对象 13 System.out.println(u.getUser_name());
以上是关于hibernate缓存(一级缓存二级缓存)的主要内容,如果未能解决你的问题,请参考以下文章