缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器,其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用的运行性能。Hibernate在进行读取数据的时候,根据缓存机制在相应的缓存中查询,如果在缓存中找到了需要的数据(我们把这称做“缓存命中"),则就直接把命中的数据作为结果加以利用,避免了大量发送SQL语句到数据库查询的性能损耗。
Hibernate缓存分类:
一、Session缓存(又称作事务缓存):Hibernate内置的,不能卸除。
缓存范围:缓存只能被当前Session对象访问。缓存的生命周期依赖于Session的生命周期,当Session被关闭后,缓存也就结束生命周期。
二、SessionFactory缓存(又称作应用缓存):使用第三方插件,可插拔。
缓存范围:缓存被应用范围内的所有session共享。这些session有可能是并发访问缓存,因此必须对缓存进行更新。缓存的生命周期依赖于应用的生命周期,应用结束时,缓存也就结束了生命周期,二级缓存存在于应用程序范围。
Hibernate一些与一级缓存相关的操作(时间点):
数据放入缓存:
1. save()。当session对象调用save()方法保存一个对象后,该对象会被放入到session的缓存中。
2. get()和load()。当session对象调用get()或load()方法从数据库取出一个对象后,该对象也会被放入到session的缓存中。
3. 使用HQL和QBC等从数据库中查询数据。
例如:数据库有一张表如下:
使用get()或load()证明缓存的存在:
- 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先检索缓存中是否有该查找对象,发现正好有该查找对象,就从缓存中取出来,不再去数据库中检索。
数据从缓存中清除:
1. evit()将指定的持久化对象从缓存中清除,释放对象所占用的内存资源,指定对象从持久化状态变为脱管状态,从而成为游离对象。
2. clear()将缓存中的所有持久化对象清除,释放其占用的内存资源。
其他缓存操作:
1. contains()判断指定的对象是否存在于缓存中。
2. flush()刷新缓存区的内容,使之与数据库数据保持同步。
Hibernate使用二级缓存
适合存放到第二级缓存中的数据:
1. 很少被修改的数据。
2. 不是很重要的数据,允许出现偶尔并发的数据。
3. 不会被并发访问的数据。
4. 参考数据,指的是供应用参考的常量数据,它的实例数目有限,它的实例会被许多其他类的实例引用,实例极少或者从来不会被修改。
不适合存放到第二级缓存的数据:
1. 经常被修改的数据。
2. 财务数据,绝对不允许出现并发。
3. 与其他应用共享的数据。
Hibernate如何将数据库中的数据放入到二级缓存中?注意,你可以把缓存看做是一个Map对象,它的Key用于存储对象OID,Value用于存储POJO。首先,当我们使用Hibernate从数据库中查询出数据,获取检索的数据后,Hibernate将检索出来的对象的OID放入缓存中key中,然后将具体的POJO放入value中,等待下一次再次向数据查询数据时,Hibernate根据你提供的OID先检索一级缓存,若没有且配置了二级缓存,则检索二级缓存,如果还没有则才向数据库发送SQL语句,然后将查询出来的对象放入缓存中。
为Hibernate配置二级缓存:
在主配置文件中hibernate.cfg.xml
- <property name="hibernate.cache.use_second_level_cache">true</property>
- <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
配置ehcache.xml
- <?xml version="1.0" encoding="UTF-8"?>
- <ehcache>
- <!--
- 缓存到硬盘的路径
- -->
- <diskStore path="d:/ehcache"></diskStore>
- <!--
- 默认设置
- maxElementsInMemory : 在內存中最大緩存的对象数量。
- eternal : 缓存的对象是否永远不变。
- timeToIdleSeconds :可以操作对象的时间。
- timeToLiveSeconds :缓存中对象的生命周期,时间到后查询数据会从数据库中读取。
- overflowToDisk :内存满了,是否要缓存到硬盘。
- -->
- <defaultCache maxElementsInMemory="200" eternal="false"
- timeToIdleSeconds="50" timeToLiveSeconds="60" overflowToDisk="true"></defaultCache>
- <!--
- 指定缓存的对象。
- 下面出现的的属性覆盖上面出现的,没出现的继承上面的。
- -->
- <cache name="com.suxiaolei.hibernate.pojos.Order" maxElementsInMemory="200" eternal="false"
- timeToIdleSeconds="50" timeToLiveSeconds="60" overflowToDisk="true"></cache>
- </ehcache>
在需要被缓存的对象中hbm文件中的<class>标签下添加一个<cache>子标签
- <hibernate-mapping>
- <class name="com.suxiaolei.hibernate.pojos.Order" table="orders">
- <cache usage="read-only"/>
- <id name="id" type="string">
- <column name="id"></column>
- <generator class="uuid"></generator>
- </id>
- <property name="orderNumber" column="orderNumber" type="string"></property>
- <property name="cost" column="cost" type="integer"></property>
- <many-to-one name="customer" class="com.suxiaolei.hibernate.pojos.Customer"
- column="customer_id" cascade="save-update">
- </many-to-one>
- </class>
- </hibernate-mapping>
若存在一对多的关系,想要在在获取一方的时候将关联的多方缓存起来,需要再集合属性下添加<cache>子标签,这里需要将关联的对象的hbm文件中必须在存在<class>标签下也添加<cache>标签,不然Hibernate只会缓存OID。
- <hibernate-mapping>
- <class name="com.suxiaolei.hibernate.pojos.Customer" table="customer">
- <!-- 主键设置 -->
- <id name="id" type="string">
- <column name="id"></column>
- <generator class="uuid"></generator>
- </id>
- <!-- 属性设置 -->
- <property name="username" column="username" type="string"></property>
- <property name="balance" column="balance" type="integer"></property>
- <set name="orders" inverse="true" cascade="all" lazy="false" fetch="join">
- <cache usage="read-only"/>
- <key column="customer_id" ></key>
- <one-to-many class="com.suxiaolei.hibernate.pojos.Order"/>
- </set>
- </class>
- </hibernate-mapping>
转载处:http://www.cnblogs.com/otomedaybreak/archive/2012/01/20/2328317.html
相关推荐
本文将基于压缩包中的章节文件,对Hibernate的源码进行详细解读。 首先,让我们从`chapter3`开始。这一部分主要探讨了Hibernate的核心组件,包括SessionFactory、SessionFactoryBuilder以及Configuration。...
Hibernate 源码分析过程 Hibernate 是一个基于 Java 的 ORM...Hibernate 的性能可以通过一级缓存和二级缓存来提高。一级缓存可以缓存对象的状态,二级缓存可以缓存查询结果。 Hibernate 也支持第三方缓存策略。
《Hibernate 转译中文版》是针对Java开发者的重要参考资料,它详细解读了Hibernate这一开源的对象关系映射(ORM)框架。Hibernate作为Java领域中的明星框架,极大地简化了数据库操作,使得开发人员可以专注于业务...
《Hibernate2.1.2参考手册中文版》是Java开发者不可或缺的重要资料,它详细解读了Hibernate这一开源ORM(对象关系映射)框架的使用方法和核心概念。Hibernate作为Java领域中备受推崇的数据持久化解决方案,极大地...
本篇将详细解读Hibernate中文API文档,旨在帮助开发者快速理解和掌握Hibernate的核心功能与用法。 一、Hibernate概述 Hibernate提供了一个编程模型和一组规范,将Java类与数据库表进行映射,通过面向对象的方式来...
此外,Hibernate的缓存机制,如一级缓存和二级缓存,也是提升性能的重要手段,孙卫琴详细解读了它们的工作原理和配置。 七、高级特性 《精通Hibernate》还涉及了高级主题,如Cascading(级联操作)、Lazy Loading...
综上所述,《hibernate笔记.txt》虽然部分信息难以直接解读,但从标题和描述中我们仍然能够提炼出关于分层架构设计原则的重要知识点,以及基于Hibernate框架在软件开发中所扮演的关键角色和提供的核心功能。...
“Hibernate高级特性”章节则进一步探讨了XDoclet与Hibernate映射、数据检索(包括CriteriaQuery和HQL)、数据关联(如一对一、一对多、多对多关系处理)、数据访问(PO和VO的使用)、事务管理、锁机制、分页、缓存...
《Hibernate 框架详解:聚焦于5.1.16.Final...以上就是关于Hibernate 5.1.16.Final的详细解读,希望对您在实际开发中使用Hibernate框架有所帮助。在实践中,不断探索和掌握其精髓,才能更好地发挥Hibernate的强大功能。
**Hibernate 开发文档详解** ...以上是对Hibernate开发文档的详细解读,涵盖了从基础概念到实际操作的各个方面。理解并掌握这些知识点,将有助于你在Java开发中高效地使用Hibernate,实现更加灵活和可靠的数据库操作。
SessionFactory的构建过程中,会加载实体类信息,生成元数据,并进行第二级缓存的配置。 **三、拦截器(Interceptor)与事件监听器(Listener)** Hibernate提供拦截器和事件监听器来扩展其行为。Interceptor是在特定...
**标题解读:** "hibernate.txt"暗示了文档内容将围绕Hibernate框架展开,这是Java领域内一个非常重要的对象关系映射(Object-Relational Mapping,简称ORM)工具。 **描述解析:** 虽然描述部分的信息似乎没有实质...
【标签】"传智播客 Hibernate 源码"中的关键词强调了这是传智播客教育机构提供的教程资料,专注于对Hibernate源代码的解读。传智播客通常以其详尽的教学内容和实例教学而闻名,因此,这个源码分析很可能包含了丰富的...
- 源码解读:通过阅读Hibernate 5.0.7的部分源码,加深对框架内部工作原理的理解。 - 实战案例:提供day01至day04的实战练习,涵盖基础操作到复杂业务场景的应用。 通过这个资料集,读者可以系统地学习Hibernate...
**标签解读:** "Hibernate Demo 源代码"标签再次强调了这是一个关于Hibernate的演示实例,提供源代码供学习和研究。"Demo"通常包含基础功能的实现,便于初学者理解和掌握。 **压缩包子文件:** "HibernateDemo"很...
7. **缓存机制**:介绍Hibernate的两级缓存(一级缓存和二级缓存),以及它们在提高性能方面的作用。 8. **关联映射**:讨论一对一、一对多、多对一、多对多四种关联关系的映射实现。 9. **事务管理**:阐述...
这包括XML配置文件的解读、hibernate.cfg.xml的编写,以及如何在Spring框架中整合Hibernate。此外,还会讲解如何创建实体类、定义字段属性以及关联映射,例如一对一、一对多、多对一、多对多的关系映射。 在事务...
在Chapter 13中,作者详细解读了Hibernate的事务管理,包括JTA(Java Transaction API)和JDBC事务的使用。同时,讲解了乐观锁和悲观锁的概念,以及如何在Hibernate中实现并发控制。读者将了解到如何在多线程环境下...