`
wandejun1012
  • 浏览: 2737525 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Hibernate的一二级缓存

 
阅读更多

 

1.什么是缓存?

 缓存是介于物理数据源与应用程序之间,是对数据库中的数据复制一份临时放在内存中的容器,其作用是为了减少应用程序对物理数据源访问的次数,从而提高了应用程序的运行性能。Hibernate在进行读取数据的时候,根据缓存机制在相应的缓存中查询,如果在缓存中找到了需要的数据(我们把这称做缓存命中"),则就直接把命中的数据作为结果加以利用,避免了大量发送SQL语句到数据库查询的性能损耗。

 

缓存策略提供商

提供了HashTable缓存,EHCacheOSCacheSwarmCachejBoss Cathe2,这些缓存机制,其中EHCacheOSCache是不能用于集群环境(Cluster Safe)的,而SwarmCachejBoss Cathe2是可以的。HashTable缓存主要是用来测试的,只能把对象放在内存中,EHCacheOSCache可以把对象放在内存(memory)中,也可以把对象放在硬盘(disk)上(为什么放到硬盘上?上面解释了)。

 

Hibernate缓存分类:

一、Session缓存(又称作事务缓存)Hibernate内置的,不能卸除。

缓存范围:缓存只能被当前Session对象访问。缓存的生命周期依赖于Session的生命周期,当Session被关闭后,缓存也就结束生命周期。这就是一级缓存。

二、SessionFactory缓存(又称作应用缓存):使用第三方插件,可插拔。

缓存范围:缓存被应用范围内的所有session共享,不同的Session可以共享。这些session可能是并发访问缓存,因此必须对缓存进行更新。缓存的生命周期依赖于应用的生命周期,应用结束时,缓存也就结束了生命周期,二级缓存存在于应用程序范围

一级缓存:

Hibernate一些与一级缓存相关的操作(时间点):

数据放入缓存:

1. save()。当session对象调用save()方法保存一个对象后,该对象会被放入到session的缓存中。

2. get()load()。当session对象调用get()load()方法从数据库取出一个对象后,该对象也会被放入到session的缓存中。

3. 使用HQLQBC等从数据库中查询数据。

例如:数据库有一张表如下:

 

使用get()load()证明缓存的存在:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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

其原理是:在同一个Session里面第一次调用get()方法,Hibernate先检索缓存中是否有该查找对象,发现没有,Hibernate发送SELECT语句到数据库中取出相应的对象,然后将该对象放入缓存中,以便下次使用,第二次调用get()方法,Hibernate先检索缓存中是否有该查找对象,发现正好有该查找对象,就从缓存中取出来,不再去数据库中检索,没有再次发送select语句。

数据从缓存中清除:

1. evit()将指定的持久化对象从缓存中清除,释放对象所占用的内存资源,指定对象从持久化状态变为脱管状态,从而成为游离对象。
2. clear()
将缓存中的所有持久化对象清除,释放其占用的内存资源。

其他缓存操作:

1. contains()判断指定的对象是否存在于缓存中。
2. flush()
刷新缓存区的内容,使之与数据库数据保持同步。

 

二级缓存:

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void testCache2() {
Session session1 = sf.openSession();//获得Session1
session1.beginTransaction();
Category c = (Category)session1.load(Category.class1);
System.out.println(c.getName());
session1.getTransaction().commit();
session1.close();
Session session2 = sf.openSession();//获得Session2
session2.beginTransaction();
Category c2 = (Category)session2.load(Category.class1);
System.out.println(c2.getName());
session2.getTransaction().commit();
session2.close();
}

 

 

当我们重启一个Session,第二次调用load或者get方法检索同一个对象的时候会重新查找数据库,会发select语句信息。

原因:一个session不能取另一个session中的缓存。

性能上的问题:假如是多线程同时去取Category这个对象,load一个对象,这个对像本来可以放到内存中的,可是由于是多线程,是分布在不同的session当中的,所以每次都要从数据库中取,这样会带来查询性能较低的问题。

解决方案:使用二级缓存。

1.什么是二级缓存?

SessionFactory级别的缓存,可以跨越Session存在,可以被多个Session所共享。

2.适合放到二级缓存中:

1)经常被访问

2)改动不大

3)数量有限

4不是很重要的数据,允许出现偶尔并发的数据

这样的数据非常适合放到二级缓存中的。

用户的权限:用户的数量不大,权限不多,不会经常被改动,经常被访问。

例如组织机构。

 

思考:什么样的类,里面的对象才适合放到二级缓存中?

改动频繁,类里面对象特别多,BBS好多帖子,这些帖子20000多条,哪些放到缓存中,不能确定。除非你确定有一些经常被访问的,数据量并不大,改动非常少,这样的数据非常适合放到二级缓存中的。

 

3.二级缓存实现原理:

 Hibernate如何将数据库中的数据放入到二级缓存中?注意,你可以把缓存看做是一个Map对象,它的Key用于存储对象OIDValue用于存储POJO。首先,当我们使用Hibernate从数据库中查询出数据,获取检索的数据后,Hibernate将检索出来的对象的OID放入缓存中key 中,然后将具体的POJO放入value中,等待下一次再次向数据查询数据时,Hibernate根据你提供的OID先检索一级缓存,若有且配置了二级缓存,则检索二级缓存,如果还没有则才向数据库发送SQL语句,然后将查询出来的对象放入缓存中。

 

4.使用二级缓存

1)打开二级缓存:

Hibernate配置二级缓存:

在主配置文件中hibernate.cfg.xml 

 <!-- 使用二级缓存 -->

<property name="cache.use_second_level_cache">true</property>

 <!--设置缓存的类型,设置缓存的提供商-->

<property    

  name="cache.provider_class">org.hibernate.cache.EhCacheProvider

</property>

2)配置ehcache.xml

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<ehcache>
<!--
缓存到硬盘的路径
-->
<diskStore path="d:/ehcache"/>
<defaultCache
maxElementsInMemory="200"<!-- 最多缓存多少个对象 -->
eternal="false"<!-- 内存中的对象是否永远不变 -->
timeToIdleSeconds="50"<!--发呆了多长时间,没有人访问它,这么长时间清除 -->
timeToLiveSeconds="60"<!--活了多长时间,活了1200秒后就可以拿走,一般Live要比Idle设置的时间长 -->
overflowToDisk="true"<!--内存中溢出就放到硬盘上 -->
/>
<!--
指定缓存的对象,缓存哪一个实体类
下面出现的的属性覆盖上面出现的,没出现的继承上面的。
-->
<cache name="com.suxiaolei.hibernate.pojos.Order"
maxElementsInMemory="200"
eternal="true"
timeToIdleSeconds="0"
timeToLiveSeconds="0"
overflowToDisk="false"
/>
</ehcache>

 

 

3)使用二级缓存需要在实体类中加入注解:

需要ehcache-1.2.jar:

还需要 commons_loging1.1.1.jar

@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)

Load默认使用二级缓存,就是当查一个对象的时候,它先会去二级缓存里面去找,如果找到了就不去数据库中查了。

Iterator默认的也会使用二级缓存,有的话就不去数据库里面查了,不发送select语句了。

List默认的往二级缓存中加数据,假如有一个query,把数据拿出来之后会放到二级缓存,但是执行查询的时候不会到二级缓存中查,会在数据库中查。原因每个query中查询条件不一样。

4)也可以在需要被缓存的对象中hbm文件中的<class>标签下添加一个<cache>子标签:

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<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

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<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>

 

 

 

refurl:http://flyingsnail.blog.51cto.com/5341669/1282367

分享到:
评论

相关推荐

    hibernate一级缓存和二级缓存的区别与联系

    总结来说,Hibernate 的一级缓存和二级缓存都是为了提高数据访问效率,但它们在范围和并发控制方面有所不同。一级缓存是事务级别的,保证了数据的强一致性,而二级缓存提供了更多的灵活性,可以跨事务共享,但需要...

    hibernate一级缓存、二级缓存和查询缓存

    **hibernate一级缓存、二级缓存和查询缓存** 在Java的持久化框架Hibernate中,缓存机制是提高应用程序性能的关键要素。缓存能够减少数据库的访问次数,提高数据读取速度,并且在一定程度上降低了系统的负载。本文将...

    Hibernate 一级缓存和二级缓存的区别

    Hibernate 一级缓存和二级缓存的区别

    Hibernate二级缓存

    Hibernate二级缓存是一种提高应用程序性能的技术,它将数据存储在SessionFactory级别的缓存中,使得数据可以在不同的Session之间共享。这与一级缓存(Session级别)不同,一级缓存仅存在于单个Session生命周期内,当...

    hibernate二级缓存实例

    总的来说,"hibernate二级缓存实例"是一个很好的学习资源,它可以帮助我们理解二级缓存的工作机制,掌握如何在项目中配置和使用,以及注意潜在的问题和优化策略。通过实践,我们可以更好地运用这一技术,提升Java...

    Spring集成的Hibernate配置二级缓存

    在Hibernate中,一级缓存是每个Session内部的缓存,它自动管理实体的状态,当一个实体被加载到Session后,该实体的状态就会被缓存。然而,一级缓存的范围仅限于单个Session,当Session关闭后,其中的数据就会丢失。...

    Hibernate一级缓存和二级缓存

    标题“Hibernate一级缓存和二级缓存”指的是Hibernate框架中的两种缓存机制,它们是提高数据访问性能的关键要素。一级缓存是Session级别的,而二级缓存是SessionFactory级别的,两者在数据库操作中起到了重要的作用...

    Hibernate一级缓存、二级缓存以及查询缓存实例

    本文将深入探讨Hibernate的一级缓存、二级缓存以及查询缓存,通过具体的实例来阐述它们的工作原理和使用方法。 首先,我们从一级缓存开始。一级缓存是Hibernate默认提供的缓存,它是每个Session级别的,也被称为...

    day37 05-HIbernate二级缓存:一级缓存更新同步到二级缓存及二级缓存配置文件

    本篇文章将深入探讨Hibernate的二级缓存机制,以及如何进行一级缓存与二级缓存的同步,同时还会介绍二级缓存的配置文件设置。 一级缓存是Hibernate默认提供的缓存,每个SessionFactory实例都有一个一级缓存。当对象...

    hibernate 二级缓存详解

    Hibernate 二级缓存是针对SessionFactory级别的全局缓存,与一级缓存(Session级别)不同,一级缓存只在单个Session生命周期内有效。二级缓存则允许不同Session之间共享数据,提高了数据访问效率,减少了对数据库的...

    hibernate一级和二级缓存配置与详解

    本篇将深入探讨Hibernate的一级缓存和二级缓存,以及查询缓存的配置和使用。 ### 一级缓存 一级缓存是Hibernate默认提供的缓存,它是Session级别的,每个Hibernate Session都有一个私有的、本地的一级缓存。当我们...

    为Spring集成的Hibernate配置二级缓存

    一级缓存是每个Session内部的缓存,而二级缓存则是SessionFactory级别的,它可以被多个Session共享。二级缓存主要由第三方缓存提供者如Ehcache、Infinispan等实现,它们将数据存储在内存或磁盘中,以便于快速访问。 ...

    hibernate二级缓存示例源码

    **hibernate二级缓存详解** Hibernate作为Java领域中广泛使用的对象关系映射(ORM)框架,极大地简化了数据库操作。然而,在处理大量数据时,性能优化显得尤为重要,这就是二级缓存的作用。本文将深入探讨Hibernate...

    hibernate5.1二级缓存包

    二级缓存是相对于一级缓存(Session 缓存)而言的,一级缓存是每个 Hibernate Session 内部的缓存,而二级缓存则是在 SessionFactory 级别的,可以被多个 Session 共享。它能够存储对象的状态,避免频繁的数据库交互...

    springboot+jpa(hibernate配置redis为二级缓存) springboot2.1.4

    通常,一级缓存由Hibernate Session管理,而二级缓存则可以跨越多个Session进行共享。 在Spring Boot项目中配置Redis作为Hibernate的二级缓存,我们需要以下步骤: 1. **添加依赖**: 首先,在`pom.xml`文件中...

    hibernate的一级缓存和二级缓存

    《深入理解Hibernate的一级缓存与二级缓存》 Hibernate作为一款强大的ORM框架,其缓存机制是优化数据库操作性能的关键之一。缓存主要分为一级缓存和二级缓存,它们各自承担着不同的职责,共同提升了数据访问的效率...

    hibernate二级缓存包

    Hibernate二级缓存是Java开发中使用Hibernate框架进行数据持久化时优化性能的一种重要技术。它在一级缓存(Session级别的缓存)的基础上,提供了一个全局的、跨会话的数据存储层,可以显著减少对数据库的访问,从而...

    Hibernate4二级缓存实例(源码)

    1. **Hibernate二级缓存**:二级缓存是Hibernate在一级缓存(Session级别的缓存)之外提供的全局共享缓存,可以跨Session共享数据。它允许多个并发用户访问相同的数据,减少对数据库的访问次数,提高系统性能。 2. ...

    hibernate二级缓存java包下载

    二级缓存是 Hibernate 缓存策略的一部分,它在应用程序的多个会话之间共享数据,进一步优化了数据库访问效率。 二级缓存分为以下关键知识点: 1. **一级缓存与二级缓存的区别**: - 一级缓存:每个 Hibernate ...

Global site tag (gtag.js) - Google Analytics