Hibernate框架之缓存

Hibernate框架之缓存

为什么要使用Hibernate缓存???

经常访问物理数据库,为了降低应用程序对物理数据源的频次,从而提高应用程序的运行性能。
缓存内的数据是对物理数据源中数据的复制,应用程序在运行时从缓存读取数据,在特定的时刻或事件会同步缓存和物理数据源的数据

Hibernate缓存原理是怎样的?

Hibernate缓存包括两大类:Hibernate一级缓存和Hibernate二级缓存。

1.Hibernate一级缓存又称为“Session的缓存”。
Session内置不能被卸载,Session的缓存是事务范围的缓存(Session对象的生命周期通常对应一个数据库事务或者一个应用事务)。一级缓存中,持久化类的每个实例都具有唯一的OID。

2.Hibernate二级缓存又称为“SessionFactory的缓存”。
由于SessionFactory对象的生命周期和应用程序的整个过程对应,因此Hibernate二级缓存是进程范围或者集群范围的缓存,有可能出现并发问题,因此需要采用适当的并发访问策略,该策略为被缓存的数据提供了事务隔离级别。
第二级缓存是可选的,是一个可配置的插件,默认下SessionFactory不会启用这个插件。
Hibernate提供了org.hibernate.cache.CacheProvider接口,它充当缓存插件与Hibernate之间的适配器。

Session延迟加载要解决的两个问题

正常关闭连接和确保请求中访问的是同一个session。
Hibernate session就是java.sql.Connection的一层高级封装,一个session对应了一个Connection。
http请求结束后正确的关闭session(过滤器实现了session的正常关闭);延迟加载必须保证是同一个session(session绑定在ThreadLocal)。

hibernate缓存分为二级。

第一级存放于session中称为一级缓存,默认带有且不能卸载。
第二级是由sessionFactory控制的进程级缓存。是全局共享的缓存,凡是会调用二级缓存的查询方法 都会从中受益。只有经正确的配置后二级缓存才会发挥作用。同时在进行条件查询时必须使用相应的方法才能从缓存中获取数据。比如Query.iterate()方法、load()、get()方法等。必须注意的是session.find()方法永远是从数据库中获取数据,不会从二级缓存中获取数据,即便其中有其所需要的数据也是如此。

查询时使用缓存的实现过程为:首先查询一级缓存中是否具有需要的数据,如果没有,查询二级缓存,如果二级缓存中也没有,此时再执行查询数据库的工作。要注意的是:此3种方式的查询速度是依次降低的。

evict(Object obj):从缓存中清除参数obj指定的持久化对象
clear():清空缓存中所有的持久化对象
一般情况下,当不希望session继续根据某个对象状态的变化来同步更新数据库时,可以使用evict()把对象从该缓存中清除,这样对象就从变成了游离态的啦,Hibernate不会把它的变化存入数据库。

Seesion seession=sessionFactory.openSession();
Transactio tx=null;
try{
    tx=session.beginTransaction();
    User user1=(User)session.load(User.class,new Integer(1));
    session.evivt(user1);    将user1清除session缓存

     User user2=(User)session.load(User.class,new Integer(1));
     System.out.println(user1==user2);    结果打印为false
     user1.setRealname("user1");   不会被保存
     user2.setRealname("user2");   会被保存
     tx.commit();
     Tread.sleep(500);
}

上面的代码从数据库中加载user1,然后调用evict()方法把它从session中清除,接着重新从数据库中加载user2它和user1的id相同,最后分别给它们的realname属性赋值,并提交事务

缓存和连接池的区

缓存和池都是放在内存里,实现是一样的,都是为了提高性能的。但有细微的差别,池是重量级的,里面的数据是一样的,比如一个池里放100个Connection连接对象,这个100个都是一样的。缓存里的数据,每个都不一样。比如读取100条数据库记录放到缓存里,这100条记录都不一样。

缓存主要是用于查询

Student student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
//不会发出查询语句,load使用缓存
student = (Student)session.load(Student.class, 1);
System.out.println("student.name=" + student.getName());
第二次查询第一次相同的数据,第二次load方法就是从缓存里取数据,不会发出sql语句到数据库里查询。
//同一个session,发出两次get方法查询
Student student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());
//不会发出查询语句,get使用缓存
student = (Student)session.get(Student.class, 1);
System.out.println("student.name=" + student.getName());

一级缓存
Hibernate中的第一级缓存
Hibernate的一级缓存由Session提供,只存在于Session的生命周期中,当应用程序调用Session接口的save(),update(),saveOrupDate(),get(),load()或者Query和Criteria实例的list(),iterate()等方法时,如果Session缓存中没有相应的对象,hibernate就会把对象加入到一级缓存中,当session关闭时,该Session所管理的一级缓存也会立即被清除;

二级缓存的管理
evict(Class arg0, Serializable arg1)将某个类的指定ID的持久化对象从二级缓存中清除,释放对象所占用的资源。
sessionFactory.evict(Customer.class, new Integer(1));
evict(Class arg0) 将指定类的所有持久化对象从二级缓存中清除,释放其占用的内存资源。
sessionFactory.evict(Customer.class);
evictCollection(String arg0) 将指定类的所有持久化对象的指定集合从二级缓存中清除,释放其占用的内存资源。
sessionFactory.evictCollection(“Customer.orders”);

重点:第一次执行了get方法查询了数据库,产生了一条sql语句,第二次执行get方法时,由于在一级缓存中找到了该对象,因此不会查询数据库,不再发出sql语句;

两次执行get方法时都查询了数据库,产生了两条sql语句,原因在于,第一次执行get方法查询出结果后,关闭了session,缓存被清除了,第二次执行get方法时,从缓存中找不到结果,只能到数据库查询;
参考博客:
http://blog.csdn.net/an_2016/article/details/52088712
http://blog.csdn.net/mohedong/article/details/52433882

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值