实体对象的状态和Hibernate的一二级缓存及特性

实体类对象的状态(概念)

实体类状态有三种:

瞬时态:

对象里面没有id值,对象与session没有关联。

//瞬时态一般是做添加操作。
//对象与session没有关系是因为.save();里面可以传任何的对象进去,和Book类没有直接的联系。
Book book=new Book("逻辑思维训练",36);
session.save(book);

持久态:

对象里面有id值,对象与session有关联。

//对象有id值,并且通过session查询了出来。
Book book=session.get(Book.class,1);
//而session有关系是因为,session直接的返回值为Book类型。Book类型和session通过泛型起到了绑定的关系。

托管态:

对象有id值,对象与session没有关联。

Book book=new Book(3,"大话数据结构",65);
session.delete(book);

Hibernate的一级缓存

什么是缓存:

数据存到数据库里面,数据库本身是文件系统,使用流的方式操作文件,效率不是很高。

  • 把数据存到内存里面,不需要使用流的方式,可以直接读取内存中的数据。
  • 把数据放到内存中,提高读取效率。

Hibernate缓存

Hibernate框架中提供了很多的优化方式,hibernate的缓存就是一种优化方式

hibernate缓存特点

第一类:hibernate的一级缓存:

  • hibernate的一级缓存默认是打开的。
  • hibernate的一级缓存使用范围是session的范围,从session创建到session关闭的范围。
  • hibernate的一级缓存中,存储数据必须 为持久态数据。(也就是有id,并且依赖session)

第二类:hibernate的二级缓存

  • 目前已经不使用了,替代技术 redis。
  • 二级缓存默认不是打开的,需要配置。
  • 二级缓存使用范围,是sessionFactory范围。

验证一级缓存的存在:

//java代码
public static void showCatch(){
        SessionFactory sessionFactory=HibernateUtils.getSessionFactory();
        Session session=sessionFactory.openSession();

        Transaction transaction=session.beginTransaction();

        Book book1=session.get(Book.class, 1);
        System.out.println(book1);
        Book book2=session.get(Book.class, 1);
        System.out.println(book2);

        transaction.commit();

        session.close();
}
//输出结果
Hibernate: 
    select
        book0_.id as id1_0_0_,
        book0_.bookname as bookname2_0_0_,
        book0_.price as price3_0_0_ 
    from
        book book0_ 
    where
        book0_.id=?
Book [bookname=精进:如何成为一个厉害的人, price=50, id=1]
Book [bookname=精进:如何成为一个厉害的人, price=50, id=1] //在这里可以看到,并没有发送sql语句,而是直接就查询输出了,很明显这是查询的一级

缓存中的内容。

一级缓存的执行过程:

Book book1=session.get(Book.class, 1);
//在第一次通过session.get(Object);方法获取数据的时候,Hibernate会通过实体类的类型和id(主键)在一级缓存中查找是否缓存中有数据,没有查找到才

会到数据库里面去找。在hibernate获取到数据之后会把数据放到一级缓存中去,该数据是一个对象。记住是一个对象,很多开发者认为是存的数据,其实是存

的对象,也就是该对象的引用。等下我会证明!!

Book book2=session.get(Book.class,1);
//所以这次你才会看到并没有输出底层的数据库sql语句。
//因为Hibernate直接从自己的一级缓存中读取到数据了。读取方式是判断当前类型是否和一级缓存中的类型相同,如果相同再判断id是否相同,都相同就把该

对象的引用返回给我们。

上面说Hibernate中存储的是对象的引用,下面我来证明!!

    public static void showCatch(){
        SessionFactory sessionFactory=HibernateUtils.getSessionFactory();
        Session session=sessionFactory.openSession();

        Transaction transaction=session.beginTransaction();

        Book book1=session.get(Book.class, 1);
        System.out.println(book1);
        book1.setPrice(30);

        Book book2=session.get(Book.class, 1);
        System.out.println(book2);
        System.out.println(book1==book2);

        transaction.commit();

        session.close();
}
//输出结果

Hibernate: 
    select
        book0_.id as id1_0_0_,
        book0_.bookname as bookname2_0_0_,
        book0_.price as price3_0_0_ 
    from
        book book0_ 
    where
        book0_.id=?
Book [bookname=精进:如何成为一个厉害的人, price=50, id=1]
Book [bookname=精进:如何成为一个厉害的人, price=30, id=1]
true//看到没有!!!这里为true。这是关键!!!
Hibernate: 
    update
        book 
    set
        bookname=?,
        price=? 
    where
        id=?

//可以看到,我们在上面java代码中把price的值从50修改为30后,当我们再次执行session.get(Object)获取目标对象,可以看到输出来的值是30。当我们让

两个对象比较引用的时候,返回结果是true。所以这就很明显了。Hibernate一级缓存中存储的是对象的引用。最后当我们通过transaction.commit()方法提交

事务后,Hibernate还会通过某种方法判断一级缓存中的数据是否被修改,如果修改后还会作更新数据库的操作。自动更新数据库的操作是Hibernate的一个特

性。这个特性只针对 持久态 有效。

再来看看下面的代码:

public static void showCatch(){
        SessionFactory sessionFactory=HibernateUtils.getSessionFactory();
        Session session=sessionFactory.openSession();

        Transaction transaction=session.beginTransaction();

        Book book1=session.get(Book.class, 1);
        System.out.println(book1);
        book1.setPrice(50);

        transaction.commit();

        session.close();
}
//输出结果

Hibernate: 
    select
        book0_.id as id1_0_0_,
        book0_.bookname as bookname2_0_0_,
        book0_.price as price3_0_0_ 
    from
        book book0_ 
    where
        book0_.id=?
Book [bookname=精进:如何成为一个厉害的人, price=30, id=1]
Hibernate: 
    update
        book 
    set
        bookname=?,
        price=? 
    where
        id=?
//很明显可以看到,再重新设置数据后就会更新数据库。

上面我们说了Hibernate还会通过某种方法判断一级缓存中的数据是否被修改,如果修改后还会作更新数据库的操作。

这个过程是Hibernate一级缓存的特性。

它有两个作用:

  1. 因为Session的生命期往往很短,存在于Session内部的最快缓存的生命期当然也很短,所以第一级缓存的命中率是很低的。其对系统性能的改善也是很有限的。
  2. 其主要作用是保持Session内部数据状态同步。

上面说到判断一级缓存中的数据是否被修改的方法是:

  • 当我们修改user对象里面的值,就会修改到一级缓存中的实体对象的值。
  • 其实在我们没有修改值之前,也就是刚查询出来之后,该实体对象会在一级缓存相对应的快照区保存一个快照。
  • 快照大家都懂,就是把实体对象的值复制拷贝一份出来。形成一个新的实体对象。
  • 当我们执行方法transaction.commit()时,里面就会比较快照区和一级缓存中的数据是否一致,如果不一致就会拿一级缓存中的数据去更新数据库中的数据。
  • 注意这里的一级缓存是存储的我们第一次查询出来的实体对象引用。
  • 判断是否一级缓存中存储的为我们查询出来的实体对象引用,关键就是我们通过判断两次在一个session中获取的结果对象引用是相同的。也就是我们上面输出true。
  • 最后,我们用session.get(Object);获取值的路径是从一级缓存中读取的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值