Hibernate之一级缓存

时间:2017-1-20 14:48

——一级缓存

1、什么是缓存
    缓存是将数据库、硬盘上的文件中的数据,放入到缓存中。
    缓存就是内存中的一块空间,当再次使用数据时,可以直接从内存中获得。

2、缓存的优点
    提高程序运行的效率,缓存技术是Hibernate的一个优化手段。

3、Hibernate分为两个级别的缓存:
    1)一级缓存:
        Session级别的缓存,一级缓存与Session生命周期一致,是自带的,不可卸载。
        一级缓存缓存的是对象的引用。
 
    2)二级缓存:
        SessionFactory级别的缓存,不是自带的,如果想要使用,则必须配置。

4、理解Session缓存(一级缓存)
    1)在Session接口的实现中包含了一系列的Java集合,这些Java集合构成了Session缓存,只要Session实例没有结束生命周期,存放在它缓存中的对象也不会结束生命周期。
    2)当Session的save()方法持久化一个对象时,该对象被载入一级缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中,当视图get()、load()获取对象时,会判断缓存中是否存在该对象,有则返回,此时不再查询数据库,没有再查询数据库。
    3)Session能够在某些时间点,按照缓存中对象的变化来执行相关的SQL语句,来同步更新数据库,这一过程被成为刷出缓存(flush)
    4)默认情况下,Session在以下时间点刷出缓存:
        *   当应用程序调用Transaction的commit()方法时,该方法先刷出缓存(session.flush()),然后再向数据库提交事务。
        *   当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,会先刷出缓存,以保证查询结果能够反应持久化对象的最新状态。
        *   调用session的flush()方法。

——证明Hibernate一级缓存的存在

示例代码:

    public void fun3(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
 
        // save()方法可以向一级缓存中存放数据
        Book book = new Book();
        book.setName("Hibernate");
        book.setAuthor("张三");
        book.setPrice(50D);
 
        Integer id = (Integer)session.save(book);
 
        // 第一次查询会发送SQL语句
        Book book1 = (Book)session.get(Book.class, 1);
 
        System.out.println(book1);
 
 
        // 第二次查询不会发送SQL语句,并且获取到的对象地址也是相同的,因为第一次查询已经将对象放入缓存了
        Book book2 = (Book)session.get(Book.class, 1);
 
        System.out.println(book2);
 
        tx.commit();
        session.close();
    }


——Hibernate快照区

当session加载了customer对象后,会为customer对象的值类型的属性复制一份快照。
当刷出缓存时,通过比较对象的当前属性和快照,来判断对象的哪些属性发生了变化,如果对象的属性和快照区一致,则不执行update操作。
自动更新数据库是依赖了快照区。

快照的存才提高了Hibernate的执行效率。

可以通过断点进行查看。 
 

示例代码:
    public void fun4(){

        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
 
        // 获得一个持久态对象
        Book book = (Book)session.load(Book.class, 2);
        book.setName("Hibernate");
 
        /*
         * 当修改对象和数据库中数据一致时,不会提交更新语句
         * 通过快照区来判断数据是否一致
         */
 
        tx.commit();
        session.close();
    }


——一级缓存的管理

一级缓存与Session的生命周期相关,Session的生命周期结束,一级缓存也就销毁了。

Session中的方法:
    *   flush()
        将缓存中的数据刷出到数据库。
    *   clear()
        清空缓存中所有数据。
    *   evict()
        清空指定对象一级缓存数据,使对象变为离线态。
    *   refresh()
        使用快照区将一级缓存中的数据覆盖,使一级缓存中的数据变为从数据库查询时的初始状态。

示例代码:

    // 一级缓存的管理:clear() / evict()
    public void fun5(){
        Session session = HibernateUtils.openSession();
        Transaction tx = session.beginTransaction();
 
        Book book1 = (Book) session.get(Book.class, 1);
        Book book2 = (Book) session.get(Book.class, 2);
        System.out.println(book1);
        System.out.println(book2);
 
        // session.clear(); // 清空一级缓存区域
        session.evict(book1); // 清空一级缓存中的指定对象
 
        Book book3 = (Book) session.get(Book.class, 1);
        Book book4 = (Book) session.get(Book.class, 2);
        System.out.println(book3);
        System.out.println(book4);
 
        tx.commit();
        session.close();
    }


——一级缓存的刷出时机

FlushMode类:
    常量:
        *   ALWAYS
            普通查询、手动flush()、事务提交都会刷新。
        *   AUTO(默认值)
            有些查询会刷出缓存,手动调用flush()、事务提交会刷出。
        *   COMMIT
            只有在事务提交时、手动调用flush()会刷出。
        *   MANUAL
            只有在flush()时刷出。
        *   NEVER
            已过时,用MANUAL替代。

    严格程度:MANUAL > COMMIT > AUTO > ALWAYS


通过session.setFlushMode(FlushMode.AUTO)进行设置,一般不会修改其值。


——操作持久化对象的方法

1、save()
    1)session的save()方法使一个瞬时对象转变为持久态对象
    2)session的save()方法完成以下操作:
        *   把瞬时对象加入到Session缓存中,使它进入持久化状态。
        *   选用映射文件指定的标识符生成器,为持久化对象分配唯一的OID,在使用代理主键的情况下,setId()方法为瞬时对象设置OID是无效的。
        *   计划执行一条insert语句,把Customer对象当前的属性值组装到insert语句中。
    3)Hibernate通过持久化对象的OID来维持它和数据库相关记录的对应关系,当Customer对象处于持久化状态时,不允许程序随意修改它的ID。

2、update()
    1)session的update()方法使一个脱管对象转变为持久化对象,并且计划执行一条update语句。
    2)在<class>标签上设置select-brefore-update="true",会在更新之前先查询,如果数据存在并且与待更新数据一致,则不执行更新。

3、saveOrUpdate()
    1)根据对象的不同状态执行save()或update()方法。
        *   如果一个对象是瞬时态对象:执行save()方法
        *   如果对象是一个脱管态对象:执行update()方法
    如果在执行update()时设置的id不存在,会报错,可以在<id>标签上设置一个unsaved-value="-1",这样如果设置的id是-1,则会继续自动生成主键并save()

4、delete()
    将持久态对象转换为瞬时态对象。

5、get() / load()
    获得一个持久态对象。

——总结

1、Hibernate中两个基本缓存
    *   一级缓存:与Session生命周期一致
    *   二级缓存:与SessionFactory生命周期一致
2、证明一级缓存的存在
3、一级缓存的结构 - 快照区
    *   用来自动完成数据库更新操作
4、Hibernate一级缓存的管理
    *   clear()
    *   evict()
    *   flush()
    *   refresh()
5、一级缓存刷出时机
    *   ALWAYS
    *   AUTO:默认值
    *   COMMIT:事务提交/flush()时刷出
    *   MANUAL:手动flush()时刷出
6、操作持久化对象常用方法
    *   save()
    *   update()
    *   saveOrUpdate()
    *   delete()
    *   get() / load() 

原文地址:https://www.cnblogs.com/wwwwyc/p/6375458.html