Hibernate学习笔记(4)之缓存

本文详细介绍了Hibernate的二级缓存,包括缓存类型、对象缓存、集合缓存和查询缓存的使用,以及Update和Delete对缓存的影响。讨论了Session管理方案,1+N问题的解决方案,以及Hibernate事务隔离级别和OpenSession与GetCurrentSession的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

二级缓存

Hibernate有一个自己的二级缓存,不推荐使用,hibernate内部测试用的。

使用二级缓存需要在配置文件中指定缓存提供商。

<propertyname="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>


一级缓存:session级别的缓存

二级缓存:SessionFactory级别的缓存,可以跨越session存在

缓存的类型

对象缓存、集合缓存、查询缓存

三种类型的打开方式


1.        二级缓存使用的对象:不敏感数据、经常访问、改动不大、数量有限。

2.        指定缓存对象的方式:

1)        在主配置文件中设置(推荐使用)

2)        在映射文件中配置

3.        指定要缓存的实体类:见上图。

对象缓存

1.        通过get(xxx.class,index)的方式获得的对象,会加入到一级和二级缓存中。

2.        当关闭session后,再次创建一个session,同样通过get方式获取对象时,首先查找二级缓存。若二级缓存有的话直接从二级缓存获得。若没有才查询数据库。

集合缓存

1.        开启集合缓存后,需要同时开启集合内存储对象的二级缓存。

2.        原因:若不开其集合中的二级缓存的后果是会产生跟多的数据库查询

Ø  首先加载Department对象,(Department类开启二级缓存、类中集合属性也开启二级缓存)

Ø  Department对象缓存到二级缓存中。其中的集合由于也开启了二级缓存,故也被缓存到二级缓存中。但是由于集合存储的类没有设置开启二级缓存,故其内容没有缓存,实际在集合中缓存的是id值。

Ø  当重新session访问对象的一般属性时,由于Department对象被缓存,所以该对象的数据可以直接从二级缓存中获取。

Ø  当访问集合中对象时,由于集合中只缓存了Id,所以会根据id值依次查询数据库。故产生了更多的数据库操作。

查询缓存(List和Iterator的不同之处)

1.        List:默认往二级缓存中加载数据,但是查询的时候不使用。

2.        Iterator:在使用HQL方式查询时,如果用Iterator()方法,就会使用二级缓存。

Ø  因为这个方法是先查询所有符合条件的id集合。

即select  id from Employee  where  id<10;

Ø  获得上面的id集合之后,在一个一个的按id查找数据,就使用上缓存了。但这个方法会有N+1次查询问题,提升性能有限,不太常用。

Ø  第二次查询时:首先还是要查询所有的id集合。

Ø  然后,根据id若有则从二级缓存中获取对象,若没有则查询数据库。

3.        Load:默认使用二级缓存。即先从二级缓存中找,没有才查数据库。

4.        更专业的查询缓存:


Ø  使用list,并使用setCacheable(true),说明开启二级缓存。

Ø  同时在主配置文件中,开启查询缓存。见上图。

<propertyname="cache.use_query_cache">true</property>

Ø  原理:一条件作为id,将查询的所有结果作为值。故只有条件【一样】值才能从二级缓存中找出数据。

Update和Delete对二级缓存的影响(时间戳缓存)

1.        Update和Delete对一级缓存的影响:数据库改变,一级缓存的内容没有发生改变。

2.        对二级缓存的影响:

第一次使用上述两个方法后,会让二级缓存中相关的数据失效,下次使用这些数据时会重新到数据库中加载。

Session管理方案

1.        要想使用SessionFactory.getCurrentSession()方法需要在Hibernate主配置文件中配置current_session_context_class项。

2.        getCurrentSession()方法:

1)        去指定的上下文中(如thread)查找绑定的Session对象,如果有就返回。

2)        如果没有,就创建一个并绑定好,然后返回

3)        当使用getCurrentSession时,Hibernate会在提交或回滚后自动的关闭Session

3.        openSession()只是开启一个新的Session,不会做绑定和查找操作。

什么是1+N问题(面试题:阐述+解决方案,背)

1.        画图解释

1)        典型的是one-to-many中:当获取一个部门对象的时候,hibernate会把跟这个部门相关的所有员工查出来。

2)        Many-to-one:获取员工表中所有员工时(一条SQL语句就可以搞定),但hibernate会通过外键一个一个地把员工对应的部门也同时加载出来(N条SQL语句)。

2.        解决方案

1)        one-to-many:在Department映射文件中,将员工属性lazy=”true”;

many-to-one:在Employee映射文件中,设置部门属性lazy=”true”;

置为lazy不是不加载,而是延迟到使用时在加载。

2)        join fetch:

修改hql语句为--"  from Employ e leftjoin fetch e.department  "

3)        QBC(Query By Criteria)

使用QBC的 createCriteria(*.class)执行查询 也可避免N+1问题

Hibernate中的事务隔离级别(面试重要:背)

1. 设定hibernate的事务隔离级别(使用hibernate.connection.isolation配置取值1、2、4、8)

1)  hibernate.connection.isolation = 2(如果不设 默认依赖数据库本身的级别

2.  用悲观锁解决repeatable read的问题(依赖于数据库的锁)


1)       select ... for update

2)       使用另一种load方法--load(xx.class , i , LockMode.Upgrade)

a)        LockMode.None无锁的机制,Transaction结束时,切换到此模式

b)       LockMode.read在査询的时候hibernate会自动获取锁

c)       LockMode.write insert  updatehibernate 会自动获取锁

d)       以上3种锁的模式,是hibernate内部使用的(不需要设)

e)        LockMode.UPGRADE_NOWAIT是 ORACLE 支持的锁的方式

l  悲观锁和乐观锁的使用场景

Ø  考虑效率隔离级别置为2(读以提交),但还要解决不可重复读的问题。

3.       Hibernate(JPA)乐观锁定(ReadCommitted)

(详见项目hibernate_3200_Hibernate_Concurrency_Optimistic_Lock)

1)       实体类中增加version属性(数据库也会对应生成该字段,初始值为0),并在其get方法前加

2)       @Version注解,则在操作过程中没更新一次该行数据则version值加1,即可在事务提交前判断该数据是否被其他事务修改过.

        OpenSession和GetCurrentSession区别


   SessoinFactor

1.  用来产生和管理Session

2.  通常情况下每个应用只需要一个SessionFactory

3.  除非要访间多个数据库的情况

4.  关注两个方法即:openSessiongetCurrentsession

1)  open session每次都是新的,需要close

2)  getCurrentsession从上下文找,如果有,用旧的,如果没有,建新的

a)  用途,界定事务边界

b)  事务提交自动close

c)  上下文配置可参见xml文件中

<property name="current_session_context_classs">thread</property>

d)   current_session_context_class(jta、thread常用 managed、custom.Class少用)

thread 使用connection 但数据库连接管理事务

jta (全称java transaction api)-java分布式事务管理(多数据库访问)

                jta由中间件提供(jboss WebLogic等,tomcat不支持)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值