zoukankan      html  css  js  c++  java
  • 【Java EE 学习 47】【Hibernate学习第四天】【sesion】【一级缓存】【懒加载】

      一、Session概述

      1.Session 接口是 Hibernate 向应用程序提供的操纵对数据库的最主要的接口, 它提供了基本的保存, 更新, 删除和加载Java 对象的方法.

      2.理解Session的缓存

        使用缓存的目的:尽量减少访问数据库的频率

        (1)在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 存放在它缓存中的对象也不会结束生命周期

        (2)当session的save()方法持久化一个对象时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当试图load()对象时,会判断缓存中是否存在该对象,有则返回。没有在查询数据库

      3.清理缓存

         Session 具有一个缓存, 位于缓存中的对象称为持久化对象, 它和数据库中的相关记录对应. Session 能够在某些时间点, 按照缓存中对象的变化来执行相关的 SQL 语句, 来同步更新数据库, 这一过程被称为清理缓存(flush) 

      4.默认情况下 Session 在以下时间点清理缓存:

        (1)当应用程序调用 Transaction 的 commit()方法的时, 该方法先清理缓存(session.flush()),然后在向数据库提交事务(tx.commit())

        (2)当应用程序执行一些查询操作时,如果缓存中持久化对象的属性已经发生了变化,会先清理缓存,以保证查询结果能够反映持久化对象的最新状态

        (3)显式调用 Session 的 flush() 方法.

      5.flush/commit/refresh/clear四种方法的区别

        flush: 进行清理缓存(此时缓存中的数据并不丢失)的操作,让缓存和数据库同步 执行一些列sql语句,但不提交事务,;

           commit:先调用flush() 方法,然后提交事务. 则意味着提交事务意味着对数据库操作永久保存下来。

           reresh:刷新,让session和数据库同步,执行查询,把数据库的最新信息显示出来,更新本地缓存的对象状态.

           clear:清空缓存,等价于list.removeAll(); 

    二、一级缓存

      1.与二级缓存不同的是,hibernate已经内部实现了一级缓存

      2.研究一级缓存需要研究的几个问题

        (1)一级缓存的生命周期:随着session的创建而被创建,随着session的关闭而消失

        (2)一级缓存是依赖于谁存在的:session对象

        (3)怎么样把数据存放到一级缓存中:使用get、load、save、update方法能够将数据存放到一级缓存中

        (4)怎么样从给一级缓存中获取数据:使用正常手段获取,如get、load,hibernate自动判断是否需要从一级缓存中获取数据

        (5)怎么样把缓存中的数据同步到数据库:使用flush方法

        (6)怎么样吧数据库中的数据同步到一级缓存中:使用refresh方法

        (7)一级缓存的特性

        (8)从一级缓存中清除某个对象:使用evict方法

        (9)清空一级缓存中所有的数据:使用clear方法

      3.测试一级缓存:https://github.com/kdyzm/day44_hibernate02

    三、懒加载

      1.什么是懒加载:懒加载实际上就是“延迟加载”,这是属于优化策略的一种方法,当使用到的时候再加载是实现该技术的原理。

              最终目的:针对数据库中的大数据,不希望特别早的加载到内存中,当用到它的时候才加载

      2.懒加载策略分为三种:

        (1)类的懒加载

        (2)集合的懒加载

        (3)单端关联的懒加载

      3.类的懒加载

        (1)类的懒加载默认开启,在映射文件中的class标签上的lazy属性为true即开启了懒加载(默认为true),为false就关闭了懒加载。

        (2)必须使用load方法才能实现懒加载

        疑问:类的懒加载不能实现?使用get方法和使用load方法效果完全相同,使用debug模式可以看出来。

      4.集合的懒加载

        (1)针对一对多或者多对多的情况。 

        (2)在持久化类对应的映射文件中的set标签中设置lazy的属性值,可以取值true、false、extra三种取值,其中最好使用extra,使用该取值的时候能够实现最彻底的懒加载。也就是说使用true开启懒加载不如使用extra开启懒加载。

          最明显的例子就是使用一下代码测试的时候:

    public void testTwo(){
            Session session=sessionFactory.openSession();
            
            Student student=(Student)session.get(Student.class,1L);
            Set<Course>courses=student.getCourses();
            System.out.println(courses.size());
            
            session.close();
        }

          如果lazy属性的值为true,虽然能够实现懒加载,但是在System.out.println(courses.size());语句执行的时候,发出的查询sql为:

    Hibernate: select courses0_.sid as sid2_1_, courses0_.cid as cid1_, course1_.cid as cid0_0_, course1_.cname as cname0_0_ from course_stu courses0_ inner join test.course course1_ on courses0_.cid=course1_.cid where courses0_.sid=?

          也就是说,hibernate会将集合中的所有数据都从数据库中取出来,然而只是为了得到集合大小的值,并不需要这么做,所以可以改为extra,发出的sql语句为:

    Hibernate: select count(cid) from course_stu where sid =?

      5.单端关联懒加载

        如果根据多的一方加载一的一方则由于数据量特别少,所以怎么样都好,所以开启懒加载或者不开启懒加载都无关紧要。

        lazy的属性值发生了变化:false、proxy、no-proxy,三种取值中false是不开启懒加载,proxy相当于true,开启懒加载。

      测试代码:在上面提供的代码中新建以下java文件即可测试。

     1 package com.kdyzm.hibernate.lazy;
     2 
     3 import java.util.Set;
     4 
     5 import org.hibernate.Session;
     6 import org.hibernate.SessionFactory;
     7 import org.hibernate.Transaction;
     8 import org.hibernate.cfg.Configuration;
     9 import org.junit.Test;
    10 
    11 import com.kdyzm.hibernate.domain.Course;
    12 import com.kdyzm.hibernate.domain.Student;
    13 
    14 public class TestLazy {
    15     private static SessionFactory sessionFactory;
    16     static{
    17         Configuration configuration=new Configuration();
    18         configuration.configure();
    19         sessionFactory=configuration.buildSessionFactory();
    20     }
    21      /*
    22       * *    类的懒加载
    23       *    集合的懒加载    
    24       *    单端关联的懒加载
    25       *    */
    26     /*
    27      * 类的懒加载
    28      * 类的懒加载默认开启
    29      * 必须使用load方法开启懒加载
    30      */
    31     @Test
    32     public void testOne(){
    33         Session session=sessionFactory.openSession();
    34         Transaction transaction=session.beginTransaction();
    35         
    36         Student student=(Student)session.load(Student.class, 1L);
    37         System.out.println(student.getSname());
    38         
    39         transaction.commit();
    40         session.close();
    41     }
    42     /*
    43      * 集合的懒加载
    44      * 
    45      * 这里针对的是关联对象的懒加载问题,即Set集合什么时候进行加载。
    46      * 可以在set标签上设置lazy属性的值,如果为true则为懒加载;如果是false则关闭懒加载。
    47      * 
    48      * 集合的懒加载也是默认开启的
    49      * 这里使用get方法和使用load方法效果完全相同?
    50      * 在映射文件中配置set标签的lazy标签为false之后懒加载就失去效果了。
    51      * 
    52      * 在set标签上设置lazy属性的值为true还不如设置为extra,这样能够彻底的实现懒加载的特性。
    53      */
    54     @Test
    55     public void testTwo(){
    56         Session session=sessionFactory.openSession();
    57         
    58         Student student=(Student)session.get(Student.class,1L);
    59         Set<Course>courses=student.getCourses();
    60         System.out.println(courses.size());
    61         
    62         session.close();
    63     }
    64     /*
    65      * 单端关联的懒加载
    66      * 略。
    67      */
    68     @Test
    69     public void testThree(){
    70 
    71         Session session=sessionFactory.openSession();
    72         Transaction transaction=session.beginTransaction();
    73         
    74         transaction.commit();
    75         session.close();
    76     }
    77 }
    TestLayz.java
  • 相关阅读:
    过河卒 NOIp 2002 dp
    [POI2014]KUR-Couriers BZOJ3524 主席树
    【模板】可持久化线段树 1(主席树)
    EXPEDI
    取石子游戏 BZOJ1874 博弈
    【模板】文艺平衡树(Splay) 区间翻转 BZOJ 3223
    关于表白
    POJ 1951
    Codeforces 1032F Vasya and Maximum Matching dp
    Codeforces 1016F Road Projects
  • 原文地址:https://www.cnblogs.com/kuangdaoyizhimei/p/4829353.html
Copyright © 2011-2022 走看看