hibernate之关于Hibernate的一级、二级缓冲

简介:

Hibernate缓冲按级别共分为两种,一级缓冲(Session)和二级缓冲(SessionFactory),有的也说是三种,还有一种是查询缓冲,当然,查询缓冲是依托于二级缓冲。


ok,什么是缓冲?

   在内存里开辟一块空间把本来应该存在硬盘里面的数据,存在这个空间里面,将来,需要这块数据的时候直接在内存中获取。这个就可以简单理解为缓冲。


一级缓冲

什么是一级缓冲,一级缓冲是Hibernate默认的,不用管它。

比如下面这段代码,

1
2
3
4
5
6
7
8
9
10
11
@Test
     publicvoid findTestyijihuanchong(){
        Session s=sessionFactory.openSession();
        s.beginTransaction();
        Person person=(Person)s.load(Person. class 1 );
        System.out.println(person.getName());
        //因为Session存在缓冲,所以这个查询直接在session中取
        Person person2=(Person)s.load(Person. class 1 );
        System.out.println(person2.getName());
        s.getTransaction().commit();
     }


我们发现,只会发出一条sql语句,那么这个就是Hibernate自带的一级缓冲。


那比如下面这种情况,新开的Session呢?在系统中,多线程并发的时候,肯定不止产生一个Session,所以在优化性能时,一级缓冲往往满足不了需求,那么就有了二级缓冲

比如下面这段代码,显然发出的是两条SQL语句。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
     publicvoidfindTestyijihuanchong(){
         Sessions=sessionFactory.openSession();
         s.beginTransaction();
         Personperson=(Person)s.load(Person. class 1 );
         System.out.println(person.getName());
         s.getTransaction().commit();
         s.close();
         
         Sessions2=sessionFactory.openSession();
         s2.beginTransaction();
         Personperson2=(Person)s2.load(Person. class 1 );
         System.out.println(person2.getName());
         s2.getTransaction().commit();
         s2.close();
     }


二级缓冲




什么是二级缓冲?二级缓冲也可以理解为SessionFactory级别的缓冲,SessionFactory是生产Session的工厂,那么我们可不可以这么理解,Session关联一个指向数据库的结果集,那么下次我在发SQL的时候,我发现,SessionFactory里面已经有了一个指向这个结果集的语句,那么我是不是可以直接使用了!


具体来说,二级缓冲并不是由Hibernate来提供,是由第三方提供的缓冲插件,通常有以下几种第三方缓冲插件:

EhCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,对Hibernate的查询缓存提供了支持。

OSCache:可作为进程范围的缓存,存放数据的物理介质可以是内存或硬盘,提供了丰富的缓存数据过期策略,对Hibernate的查询缓存提供了支持。

SwarmCache:可作为群集范围内的缓存,但不支持Hibernate的查询缓存。

JBossCache:可作为群集范围内的缓存,支持事务型并发访问策略,对Hibernate的查询缓存提供了支持。

那么,哪些数据适合放在二级缓冲中,理解二级缓冲特性之后,我们知道,

1、经常被查询的数据,这样的数据需要频繁访问数据库,肯定是非常适合放在缓冲

2、很少并发的数据,什么意思呢?打个比方,一个查询,一个修改,这样很可能会造成一种脏读,或者是幻读。意思就是你的数据库的数据可能被修改了,但是设置二级缓冲还没有及时更新

3、重要的数据,这个不多说

总之,放在二级缓冲中的数据,一般都是不重要的,不经常修改的数据。比如说,菜单,比如说权限。这些都是非常适合放在二级缓冲中,比如说财务数据,工资数据等,这些不建议放在二级缓冲中

我们上面讲了二级缓冲是第三方提供的那么显然我们需要配置,

首先我们需要在我们的hibernate.cfg.xml中开启我们的二级缓冲,当然也可能是properties文件中配置

1
2
3
4
5
6
<!-- 开启缓冲 -->
< property  name = "hibernate.cache.use_second_level_cache" >true</ property >
<!--指定是哪个二级缓冲-->
< property  name = "hibernate.cache.provider_class" >org.hibernate.cache.EhCacheProvider</ property >
<!-- 使用查询二级缓冲 -->
< propertyname = "hibernate.cache.use_query_cache" >true</ property >

 第二步,我们指定是哪个实体类需要二级缓冲

Annotations配置

1
2
3
@Entity
@Cache (usage=CacheConcurrencyStrategy.READ_WRITE)
@Table (name= "p_person" )

XML配置

1
2
3
< class  name = "Person"  table = "t_person" >
         < cache  usage = "read-write" />
         < id  name = "id" >

记住XML配置一定是id之前,class之内

还必须有ehcache.xml文件,这个文件有兴趣大家可以在网上自己看一下,这里我就不讲解,里面的内容了

配置完之后,我们直接看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
     publicvoid findTesterjihuanchong(){
         Sessions=sessionFactory.openSession();
         s.beginTransaction();
         Personperson=(Person)s.load(Person.class, 1);
         System.out.println(person.getName());
         s.getTransaction().commit();
         s.close();
         
         Sessions2=sessionFactory.openSession();
         s2.beginTransaction();
         Personperson2=(Person)s2.load(Person.class, 1);
         System.out.println(person2.getName());
         s2.getTransaction().commit();
         s2.close();
     }

这个时候,我们再看,肯定又是只发送一条SQL语句了。


查询缓冲


什么是查询查询缓冲。顾明思议它是查询的时候产生的缓冲,那我们前面讲到了二级缓冲,查询缓冲和二级缓冲是什么关系?首先查询缓冲是依赖于二级缓冲的,查询缓冲一般设置在list()方法中,查询缓冲是重复查询使用的缓冲,如果你两个查询不一样,这个存在的缓冲是不起作用的。需要注意的是list()查询缓冲必须要告诉hibernate,使用查询缓冲,查询缓冲才会生效。

 

setCacheable(true)

ok,看代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Test
     publicvoid findTestList(){
         Sessions=sessionFactory.getCurrentSession();
         s.beginTransaction();
         List<Person>persons=s.createQuery( "fromPerson" ).setCacheable( true ).list();
         List<Person>person1=s.createQuery( "fromPerson" ).setCacheable( true ).list();
         for (Person person:persons){
             System.out.println(person.getName()+ "----" +person.getId());
         }
         for (Person person:person1){
             System.out.println(person.getName()+ "----" +person.getId());
         }
         s.getTransaction().commit();
     }


到这里,我们基本上做完了Hibernate缓冲,但是缓冲怎么配置,怎么使用,要根据实际的项目情况而定,并不是说,配置了二级缓冲一定会提高系统性能。同时,高级的可能也牵涉到缓冲算法等问题。当然在项目中多犯几次错误,自然就会使用Hibenrate缓冲了!


下篇博文写悲观锁和乐观锁,写完之后,我会写一篇怎么模仿开发一套属于我们自己ORM框架,基本上就写完了Hibenrate的常见特性,闲来无事,喜欢写着玩,大家随便看,有问题及时探讨。











本文转自 小夜的传说 51CTO博客,原文链接:http://blog.51cto.com/1936625305/1577057,如需转载请自行联系原作者
目录
相关文章
|
9天前
|
Java 数据库连接 mybatis
Mybatis 多级分类查询
Mybatis 多级分类查询
12 0
|
7月前
|
缓存 Java 数据库连接
深入浅出 MyBatis 的一级、二级缓存机制
深入浅出 MyBatis 的一级、二级缓存机制
107 0
|
9月前
|
缓存 Java 数据库连接
介绍一下Mybatis的一级、二级缓存
介绍一下Mybatis的一级、二级缓存
61 0
|
4月前
|
SQL 缓存 Java
JPA - 一级和二级缓存使用详解
JPA - 一级和二级缓存使用详解
113 0
|
7月前
|
缓存 Java 数据库连接
为什么?Mybatis的一级和二级缓存都不建议使用?
个人认为mybatis一级缓存和二级缓存并不是一个很好的设计,工作中我基本上也不会使用一级缓存和二级缓存,因为一旦使用不当会造成很多问题,所以我们今天就来看看到底会有什么问题? 上一节我们介绍了Executor会调用StatementHandler执行sql,起一个承上启下的作用。
|
9月前
|
XML SQL 缓存
如何理解Mybatis的一级、二级缓存 ?
MyBatis提供了一级缓存(Local Cache)和二级缓存(Global Cache)两种缓存机制,用于提高查询性能和减少数据库访问次数。
53 0
|
10月前
|
SQL 存储 缓存
深入浅出 MyBatis 的一级、二级缓存机制1
深入浅出 MyBatis 的一级、二级缓存机制
|
10月前
|
存储 SQL 缓存
深入浅出 MyBatis 的一级、二级缓存机制2
深入浅出 MyBatis 的一级、二级缓存机制2
深入浅出 MyBatis 的一级、二级缓存机制2
|
11月前
|
Java 数据库连接 mybatis
mybatis使用if标签进行单个或多个属性修改数据
mybatis使用if标签进行单个或多个属性修改数据
121 0
|
SQL XML 缓存
MyBatis中一级、二级缓存的理解和应用
MyBatis中一级、二级缓存的理解和应用
100 0