SSH与SSM学习之hibernate10——Hibernate的一级缓存
一、Hibernate的一级缓存
1 缓存是计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者
数据库)之间,
其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能。
缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存。
2 hibernate的缓存分为一级缓存和二级缓存, Hibernate的这两级缓存都位于持久化层,
存储的都是数据库数据的备份。其屮第一级缓存为hibernate的内存缓存,不能被卸载。
1.1 什么是Hibernate的一级缓存
1 Hibernate的一级缓存就是指Session缓存, Session缓存是一块内存空间,
用来存放相互管理的java对象,在使用Hibernate查询对象的时候,
首先会使用对象属性的OID值在Hibernate的一级缓存中进行查找,
如果找到匹配OID值的对象,就直接将该对象从一级缓存中取出使用,不会再查询数据库 ;
如果没有找到相同OID值的对象,则会去数据库中查找相应数据。
当从数据库中查询到所需数据时,该数据信息也会放置到一级缓存中。
hibernate的一级缓存的作用就足减少对数据库的访问次数
1.2 Hibernate的一级缓存的特点
在Session接口的实现中包含一系列的 Java集合,这些Java集合构成了 Session缓存。
只要Session实例没有结束生命周期,存放在它缓存中的对象也不会结束生命周期。
固一级缓存也被称为是Session基本的缓存。
Hibernate的一级缓存有如下特点:
当应用程序调用Session接门的save()、 update()、 saveOrUpdate时,如果Session缓存中没
有相应的对象, Hibernate就会自动的把从数据库中查询到的相应对象信息加入到一级缓存
中去。当调用Session接口的load()、 get()方法,以及Query接口的list()、 iterator()方法时,会判
断缓存中是否存在该对象,有则返回,不会查询数据库,如果缓存中没有要杳询对象,再
去数据库中杳询对应对象,并添加到一级缓存中。当调用Session的close()方法时, Session缓存会被清空
二、证明一级缓存存在
下面我们来使创建我们的代码,证明一级缓存的存在。
2.1 代码实例
/**
* 一级缓存测试一 证明一级缓存存在
*/
@Test
public void cacheTest1(){
//1.创建session
Session session = HibernateUtils.openSession();
//2.开启事务
Transaction t = session.beginTransaction();
//3.查询对象
User user1 = session.get(User.class,1);
User user2 = session.get(User.class,1);
User user3 = session.get(User.class,1);
User user4 = session.get(User.class,1);
User user5 = session.get(User.class,1);
//打印
System.out.println( "user1 == user2 : " + (user1 == user2));
System.out.println( "user1 == user3 : " + (user1 == user3));
System.out.println( "user1 == user4 : " + (user1 == user4));
System.out.println( "user1 == user5 : " + (user1 == user5));
//4.提交事务
t.commit();
//5.关闭资源
session.close();
}
2.2 运行结果
Hibernate:
select
user0_.id as id1_0_0_,
user0_.name as name2_0_0_,
user0_.age as age3_0_0_
from
tb_user2 user0_
where
user0_.id=?
user1 == user2 : true
user1 == user3 : true
user1 == user4 : true
user1 == user5 : true
2.3 分析
我们总共调用了 5 次 get 的方法,然而只执行了一次 数据库的查询操作。而且我们获取到的 5个对象都是同一个对象。这就是因为一级缓存的原因了。
2.3.1 一级缓存图示
2.3.2 一级缓存下查询分析
应用程序调用get查询id为1数据;
hibernate先从缓存中查看是否存在id为1的User的对象。如果有,直接放回缓存中的对象,如果没有执行步骤3;
hibernate发送sql到数据库中
数据库通过ResultSet放回结果到hibernate中;
如果ResultSet返回数据,那么hibernate把ResultSet中的数据组装成User对象;
把User对象存入到session缓存中;
hibernate把缓存对象返回给应用程序。
三、快照
快照其实就是一个存储了查询到的数据的集合。
3.1 代码实例
/**
* 一级缓存测试二 快照
*/
@Test
public void cacheTest2(){
//1.创建session
Session session = HibernateUtils.openSession();
//2.开启事务
Transaction t = session.beginTransaction();
//3.查询对象
User user = session.get(User.class,1);
System.out.println("查询到名称:"+user.getName());
user.setName("wiming");
user.setName("小明");
//4.提交事务
t.commit();
//5.关闭资源
session.close();
}
3.2 运行结果
Hibernate:
select
user0_.id as id1_0_0_,
user0_.name as name2_0_0_,
user0_.age as age3_0_0_
from
tb_user2 user0_
where
user0_.id=?
查询到名称:小明
3.3 分析
我们拿到的user是一个持久化状态的对象,它的所有改变都会同步到数据中。上面我们首先我们
查询到了 user 中的name是“小明”,然后我们设置了它的name为“wiming”,再然后我们又把name设置
回 “小明”,我们发现我们的这个修改不会同步到数据库。这就是快照的原因啦。
3.3.1 缓存和快照图示
3.3.2 缓存和快照下查询分析
应用程序调用get查询id为1数据;
hibernate先从缓存中查看是否存在id为1的User的对象。如果有,直接放回缓存中的对象,如果没有执行步骤3;
hibernate发送sql到数据库中
数据库通过ResultSet放回结果到hibernate中;
如果ResultSet返回数据,那么hibernate把ResultSet中的数据组装成User对象(会组装成为两个对象);
组装成的这两个对象,一个放入到session缓存中,一个放入到快照中;
hibernate把缓存对象返回给应用程序;
我们的应用程序修改了缓存中的对象;
应用程序向hibernate提交了事务,
hibernate对比缓存中对象和快照。如果有变化就会同步到数据库中。
四、持久化状态对象其实就是放入session缓存中的对象
4.1 代码实例
/**
* 一级缓存测试三
* 持久化状态对象其实就是放入session缓存中的对象
*/
@Test
public void cacheTest3(){
//1.创建session
Session session = HibernateUtils.openSession();
//2.开启事务
Transaction t = session.beginTransaction();
//3.创建对象
User user = new User();//瞬时状态。没有id,没有添加到session缓存中
user.setId(1);//游离|托管状态 。有id,没有添加到session缓存中
session.update(user);// 游离|托管状态 ----->持久化状态
// 获取id为1的对象
User user2 = session.get(User.class,1);
System.out.println("user == user2 :" + (user == user2));
System.out.println("---已经是持久化状态了,下面要执行的是commit了----");
//4.提交事务
t.commit();
//5.关闭资源
session.close();
}
4.2 运行结果
user == user2 :true
---已经是持久化状态了,下面要执行的是commit了----
Hibernate:
update
tb_user2
set
name=?,
age=?
where
id=?
4.3 分析
上面我们可以看到,我们的user通过update从游离|托管状态 变成了 持久化状态,
然而这个时候是没有执行sql的。然后我们通过 session 的get方法,获取数据,也是没有执行sql
我们获取到了 user2 ,然后我们发现 user和user2是同一个对象。最后我们提交事务,这个时候才会
去执行更新的sql语句。
由分析我们可以得出 持久化状态对象其实就是放入session缓存中的对象。
五、提高效率的手段
提高效率手段1:提高查询效率
如一级缓存。
提高效率手段2:减少不必要的修改语句发送
如快照