SSH与SSM学习之hibernate10——Hibernate的一级缓存

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 一级缓存图示

image

2.3.2 一级缓存下查询分析
  1. 应用程序调用get查询id为1数据;

  2. hibernate先从缓存中查看是否存在id为1的User的对象。如果有,直接放回缓存中的对象,如果没有执行步骤3;

  3. hibernate发送sql到数据库中

  4. 数据库通过ResultSet放回结果到hibernate中;

  5. 如果ResultSet返回数据,那么hibernate把ResultSet中的数据组装成User对象;

  6. 把User对象存入到session缓存中;

  7. 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 缓存和快照图示

image

3.3.2 缓存和快照下查询分析
  1. 应用程序调用get查询id为1数据;

  2. hibernate先从缓存中查看是否存在id为1的User的对象。如果有,直接放回缓存中的对象,如果没有执行步骤3;

  3. hibernate发送sql到数据库中

  4. 数据库通过ResultSet放回结果到hibernate中;

  5. 如果ResultSet返回数据,那么hibernate把ResultSet中的数据组装成User对象(会组装成为两个对象);

  6. 组装成的这两个对象,一个放入到session缓存中,一个放入到快照中;

  7. hibernate把缓存对象返回给应用程序;

  8. 我们的应用程序修改了缓存中的对象;

  9. 应用程序向hibernate提交了事务,

  10. 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:减少不必要的修改语句发送

如快照

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值