一、why (为什么要使用Hibernate缓存? )
Hibernate是一个经常访问物理数据库的持久层框架。
为了降低APP应用程序对物理数据源的访问频率,提高APP应用程序的性能。
缓存中的数据是物理数据源中数据的副本,APP应用程序在执行时从缓存中读取和写入数据,并在特定时间点或事件将缓存与物理数据源中的数据同步。
二、微信(hibernate缓存的原理如何? ) Hibernate缓存分为两类: hibernatel1缓存和hibernatel2缓存。
1.Hibernate一级缓存也称为会话缓存。
Session内置不能卸载。 会话的缓存是整个事务的缓存。 Session对象的生命周期通常对应于数据库事务或APP应用程序事务。
在主缓存中,持久化类的每个实例都具有唯一的OID。
2.Hibernate的l2缓存也称为会话工厂缓存。
由于SessionFactory对象的生命周期对应于整个APP应用程序进程,因此Hibernate缓存是整个进程或群集的缓存,并且可能同时出现问题,因此高速缓存数据的事务处理
l2缓存是可选的可配置插件,默认情况下不启用会话工厂。
Hibernate提供org.Hibernate.cache.cache provider接口,用作缓存插件和hibernate之间的适配器。
适合存储在辅助缓存中的数据是什么?
1 )几乎没有变化的数据
2 )允许偶尔同时发生的数据,而不是重要数据
3 )未同时访问的数据
4 )常数数据
不适合存储在l2缓存中的数据?
1 )经常修改的数据
2 )绝对不允许同时访问的数据,如财务数据,绝对不允许同时访问
3 )与其他APP应用程序共享的数据。
3.Session延迟加载实现需要解决两个问题。 要成功关闭连接,并确保请求中访问的是同一会话。
Hibernate session是java.sql.Connection的高级软件包,一个session对应一个Connection。
http请求结束后正确关闭session ()过滤器实现了session的正常关闭); 延迟加载必须确保是同一会话。 会话绑定到ThreadLocal。
4.Hibernate搜索对象如何应用缓存?
Hibernate根据ID访问数据对象时,首先从会话一级缓存开始检查;
不,如果配置了l2缓存,请从l2缓存中检查。
如果找不到,请联系数据库,并按ID在删除、更新缓存或添加数据时同时更新缓存结果。
5.l1缓存与l2缓存的比较图。
一级高速缓存
辅助缓存
保存数据的格式
相互关联的持久化对象
对象批量数据
缓存范围
事务的范围。 每个事务都有各自的一级高速缓存
进程范围或群集范围以及高速缓存由同一进程或群集范围内的所有事务共享
并发访问策略
因为每个事务都有单独的一级高速缓存,所以不会同时出现问题,所以不需要提供并发访问策略
由于多个事务同时访问l2高速缓存中的同一数据,因此必须提供适当的并发访问策略以确保特定的事务隔离级别
数据过期策略
只要APP应用程序不清空或清空特定对象,一级缓存中的对象就不会过期
必须提供数据过期策略,如基于内存的缓存中的对象最大数量、缓存中对象允许的最大时间以及缓存中对象允许的最大空闲时间
物理介质
存储器
内存、硬盘和对象的主体数据首先存储在基于内存的缓存中,当内存中的对象数量达到数据过期策略的maxElementsInMemory值时,其馀对象将存储在基于硬盘的缓存中
缓存软件的实现
Hibernate会话实现中包含的
第三方提供的Hibernate仅提供用于将特定缓存插件集成到Hibernate中的缓存适配器
如何启用缓存
在Session界面中运行保存、更新、删除、加载和查询时,Hibernate将启用一级缓存。 对于批量操作,如果不想启用一级缓存,请直接在JDBCAPI中运行
用户可以在类或类的单个集合的粒度中配置l2缓存。 如果类的实例经常读取并且很少更改,请考虑使用l2缓存。 只有在某个类或集合中配置了l2缓存时,Hibernate才会在运行时将其实例添加到l2缓存中
用户如何管理缓存
主缓存中的物理介质是内存,内存容量有限,因此,必须使用适当的搜索策略和搜索方法限制要加载的对象数量。 session evit ) )方法允许缓存中的特定对象为空,但不建议使用
使用l2缓存物理介质,可以将内存和硬盘
因此第二级缓存可以存放大容量的数据,数据过期策略的maxElementsInMemory属性可以控制内存中的对象数目,管理二级缓存主要包括两个方面:选择需要使用第二级缓存的持久化类,设置合适的并发访问策略;选择缓存适配器,设置合适的数据过期策略。SessionFactory的evit()方法也可以显示的清空缓存中特定对象,但不推荐三、how(Hibernate的缓存机制如何应用?)
1. 一级缓存的管理:
evit(Object obj) 将指定的持久化对象从一级缓存中清除,释放对象所占用的内存资源,指定对象从持久化状态变为脱管状态,从而成为游离对象。
clear() 将一级缓存中的所有持久化对象清除,释放其占用的内存资源。
contains(Object obj) 判断指定的对象是否存在于一级缓存中。
flush() 刷新一级缓存区的内容,使之与数据库数据保持同步。
2.一级缓存应用: save()。当session对象调用save()方法保存一个对象后,该对象会被放入到session的缓存中。 get()和load()。当session对象调用get()或load()方法从数据库取出一个对象后,该对象也会被放入到session的缓存中。 使用HQL和QBC等从数据库中查询数据。
public class Client
{
public static void main(String[] args)
{
Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
try
{
/*开启一个事务*/
tx = session.beginTransaction();
/*从数据库中获取id="402881e534fa5a440134fa5a45340002"的Customer对象*/
Customer customer1 = (Customer)session.get(Customer.class, "402881e534fa5a440134fa5a45340002");
System.out.println("customer.getUsername is"+customer1.getUsername());
/*事务提交*/
tx.commit();
System.out.println("-------------------------------------");
/*开启一个新事务*/
tx = session.beginTransaction();
/*从数据库中获取id="402881e534fa5a440134fa5a45340002"的Customer对象*/
Customer customer2 = (Customer)session.get(Customer.class, "402881e534fa5a440134fa5a45340002");
System.out.println("customer2.getUsername is"+customer2.getUsername());
/*事务提交*/
tx.commit();
System.out.println("-------------------------------------");
/*比较两个get()方法获取的对象是否是同一个对象*/
System.out.println("customer1 == customer2 result is "+(customer1==customer2));
}
catch (Exception e)
{
if(tx!=null)
{
tx.rollback();
}
}
finally
{
session.close();
}
}
}
结果
Hibernate:
select
customer0_.id as id0_0_,
customer0_.username as username0_0_,
customer0_.balance as balance0_0_
from
customer customer0_
where
customer0_.id=?
customer.getUsername islisi
-------------------------------------
customer2.getUsername islisi
-------------------------------------
customer1 == customer2 result is true
输出结果中只包含了一条SELECT SQL语句,而且customer1 == customer2 result is true说明两个取出来的对象是同一个对象。其原理是:第一次调用get()方法, Hibernate先检索缓存中是否有该查找对象,发现没有,Hibernate发送SELECT语句到数据库中取出相应的对象,然后将该对象放入缓存中,以便下次使用,第二次调用get()方法,Hibernate先检索缓存中是否有该查找对象,发现正好有该查找对象,就从缓存中取出来,不再去数据库中检索。
3.二级缓存的管理:
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");
4.二级缓存的配置
常用的二级缓存插件
EHCache org.hibernate.cache.EhCacheProvider
OSCache org.hibernate.cache.OSCacheProvider
SwarmCahe org.hibernate.cache.SwarmCacheProvider
JBossCache org.hibernate.cache.TreeCacheProvider
org.hibernate.cache.EhCacheProvider
true
timeToIdleSeconds="50" timeToLiveSeconds="60" overflowToDisk="true">
timeToIdleSeconds="50" timeToLiveSeconds="60" overflowToDisk="true">
/p>
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
若存在一对多的关系,想要在在获取一方的时候将关联的多方缓存起来,需要在集合属性下添加子标签,这里需要将关联的对象的hbm文件中必须在存在标签下也添加标签,不然Hibernate只会缓存OID。
原文:http://www.cnblogs.com/wean/archive/2012/05/16/2502724.html