zoukankan      html  css  js  c++  java
  • Hibernate一级缓存(基于查询分析)

    首先我们应该弄清什么是hibernate缓存:hibernate缓存是指为了降低应用程序对物理数据源的访问频次,从而提高应用程序的运行性能的一种策略。我们要将这个跟计算机内存或者cpu的缓存区分开。

    一、hibernate查询的几种方式

    既然是基于查询分析hibernate一级缓存,我们就来分析分析hibernate查询方式

    1、通过session对象的get()方法

    我们通过查看hibernate的api文档找到了session接口,并重点看了get()方法,我们主要使用一下两种get()方法:

    通过传入由实体类获得的Class类对象(姑且叫做类类型)和该类的唯一标识符两个参数,返回一个Object类型的查询对象。

    通过传入实体类名和该类对象的唯一标识符两个参数,返回一个Object类型的查询对象。

    代码示例:

     1 package com.third;
     2 
     3 import java.util.List;
     4 
     5 import org.hibernate.Query;
     6 import org.hibernate.Session;
     7 import org.hibernate.SessionFactory;
     8 import org.hibernate.Transaction;
     9 import org.hibernate.cfg.Configuration;
    10 import org.hibernate.service.ServiceRegistry;
    11 import org.hibernate.service.ServiceRegistryBuilder;
    12 import org.junit.After;
    13 import org.junit.Before;
    14 import org.junit.Test;
    15 
    16 import com.third.Dao2.Students2;
    17 import com.third.Dao2.Students2PartInfo;
    18 
    19 public class Test3 {
    20     private static SessionFactory sessionFactory;
    21     private static Session session;
    22     private static Transaction transaction;
    23     @Before
    24     public void init(){
    25         //先获取配置对象,匹配hibernate.cfg.xml文件
    26         Configuration config=new Configuration().configure();
    27         //获取注册服务对象(该对象中包含hibernate.cfg.xml中的<properties>和<maping>信息
    28         ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
    29         //获取sessionFactory对象,通过sessionFactory对象读取hibernate.cfg.xml文档信息,并通过<mapping>标签加载hbm.xml文件信息
    30         sessionFactory=config.buildSessionFactory(serviceRegistry);
    31     }
    32     
    33     @Test
    34     public void test3(){
    35         //通过sessionFactory对象获取session对象
    36         session=sessionFactory.openSession();
    37         //通过session对象开启事务,并且返回事务(transaction)对象
    38         transaction=session.beginTransaction();    
    39     
    40         //第一个session对象通过get()方法第一次查询相同记录
    41         Students2 stu1=(Students2) session.get(Students2.class, 1);
    42         //第一个session对象通过get()函数第二次查询相同记录
    43         Students2 stu2=(Students2) session.get(Students2.class, 1);
    44         System.out.println("学号:"+stu1.getSid()
    45             +"  姓别:"+stu1.getSgender()+"  姓名:"+stu1.getSname());
    46         System.out.println("学号:"+stu2.getSid()
    47         +"  姓别:"+stu2.getSgender()+"  姓名:"+stu2.getSname());
    48         
    49         //重新获得一个session对象,再一次执行session对象的get()方法查询相同记录
    50         Session session1=sessionFactory.openSession();
    51         Students2 stu3=(Students2) session1.get(Students2.class, 1);
    52         System.out.println("学号:"+stu3.getSid()
    53             +"  姓别:"+stu3.getSgender()+"  姓名:"+stu3.getSname());
    54         
    55         
    56     }
    57     
    58     @After
    59     public void destory(){
    60         transaction.commit();
    61         //关闭开启的资源
    62         if(session!=null){
    63             session.close();
    64         }
    65         if(sessionFactory!=null){
    66             sessionFactory.close();
    67         }
    68     }
    69 }

    运行结果:

    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:1  姓别:女  姓名:小美
    学号:1  姓别:女  姓名:小美
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:1  姓别:女  姓名:小美

    分析:在同一个session对象的条件下查询同一表格记录,hibernate解析的SQL语句只会执行一次,重新获得一个session对象后,再去查询相同的表格记录时,hibernate解析而成的SQL语句会在执行一次。

    我们不难得出:在同一个session对象的情况下,使用get()方法查询相同的对象会使用到缓存(一级缓存),不同的session对象在查询相同对象正常情况下是不会使用缓存。

    2、通过session的load()方法

    我们通过查看hibernate的api文档找到了session接口,并重点看了load()方法,我们主要使用一下两种load()方法:

    通过传入由实体类获得的Class类对象(姑且叫做类类型)和该类的唯一标识符两个参数,返回一个Object类型的查询对象。

    通过传入实体类名和该类对象的唯一标识符两个参数,返回一个Object类型的查询对象。

    代码示例:

     1 package com.third;
     2 
     3 import java.util.List;
     4 
     5 import org.hibernate.Query;
     6 import org.hibernate.Session;
     7 import org.hibernate.SessionFactory;
     8 import org.hibernate.Transaction;
     9 import org.hibernate.cfg.Configuration;
    10 import org.hibernate.service.ServiceRegistry;
    11 import org.hibernate.service.ServiceRegistryBuilder;
    12 import org.junit.After;
    13 import org.junit.Before;
    14 import org.junit.Test;
    15 
    16 import com.third.Dao2.Students2;
    17 import com.third.Dao2.Students2PartInfo;
    18 
    19 public class Test3 {
    20     private static SessionFactory sessionFactory;
    21     private static Session session;
    22     private static Transaction transaction;
    23     @Before
    24     public void init(){
    25         //先获取配置对象,匹配hibernate.cfg.xml文件
    26         Configuration config=new Configuration().configure();
    27         //获取注册服务对象(该对象中包含hibernate.cfg.xml中的<properties>和<maping>信息
    28         ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
    29         //获取sessionFactory对象,通过sessionFactory对象读取hibernate.cfg.xml文档信息,并通过<mapping>标签加载hbm.xml文件信息
    30         sessionFactory=config.buildSessionFactory(serviceRegistry);
    31     }
    32     
    33     @Test
    34     public void test3(){
    35         //通过sessionFactory对象获取session对象
    36         session=sessionFactory.openSession();
    37         //通过session对象开启事务,并且返回事务(transaction)对象
    38         transaction=session.beginTransaction();    
    39         
    40         //第一个session对象通过get()方法第一次查询相同记录
    41         Students2 stu1=(Students2) session.load(Students2.class, 1);
    42         //第一个session对象通过get()函数第二次查询相同记录
    43         Students2 stu2=(Students2) session.load(Students2.class, 1);
    44         System.out.println("学号:"+stu1.getSid()
    45             +"  姓别:"+stu1.getSgender()+"  姓名:"+stu1.getSname());
    46         System.out.println("学号:"+stu2.getSid()
    47         +"  姓别:"+stu2.getSgender()+"  姓名:"+stu2.getSname());
    48         
    49         //重新获得一个session对象,再一次执行session对象的get()方法查询相同记录
    50         Session session1=sessionFactory.openSession();
    51         Students2 stu3=(Students2) session1.load(Students2.class, 1);
    52         System.out.println("学号:"+stu3.getSid()
    53             +"  姓别:"+stu3.getSgender()+"  姓名:"+stu3.getSname());
    54         
    55     }
    56     
    57     @After
    58     public void destory(){
    59         transaction.commit();
    60         //关闭开启的资源
    61         if(session!=null){
    62             session.close();
    63         }
    64         if(sessionFactory!=null){
    65             sessionFactory.close();
    66         }
    67     }
    68 }

    运行结果:

    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:1  姓别:女  姓名:小美
    学号:1  姓别:女  姓名:小美
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:1  姓别:女  姓名:小美

    分析:在同一个session对象的条件下查询同一表格记录,hibernate解析的SQL语句只会执行一次,重新获得一个session对象后,再去查询相同的表格记录时,hibernate解析而成的SQL语句会在执行一次。

    我们不难得出:在同一个session对象的情况下,使用load()方法查询相同的对象会使用到缓存(一级缓存),不同的session对象在查询相同对象正常情况下是不会使用缓存。

    我们可以总结得到,load()函数的查询流程和get()函数的查询流程基本相同。

    3、通过session对象的createQuery(String HQL)方法

    我们通过查看hibernate的api文档找到了session接口,找到createQuery(String HQL)方法,该方法的返回值类型是一个Query(查询),于是,我们找到Query接口,我们找到了两个方法,是将查询结果返回的。

    以List的方式返回查询结果

    以迭代器的方式返回查询结果

    (1)以List的方式返回查询结果

    1)有select子句

     1 package com.third;
     2 
     3 import java.util.List;
     4 
     5 import org.hibernate.Query;
     6 import org.hibernate.Session;
     7 import org.hibernate.SessionFactory;
     8 import org.hibernate.Transaction;
     9 import org.hibernate.cfg.Configuration;
    10 import org.hibernate.service.ServiceRegistry;
    11 import org.hibernate.service.ServiceRegistryBuilder;
    12 import org.junit.After;
    13 import org.junit.Before;
    14 import org.junit.Test;
    15 
    16 import com.third.Dao2.Students2;
    17 import com.third.Dao2.Students2PartInfo;
    18 
    19 public class Test3 {
    20     private static SessionFactory sessionFactory;
    21     private static Session session;
    22     private static Transaction transaction;
    23     @Before
    24     public void init(){
    25         //先获取配置对象,匹配hibernate.cfg.xml文件
    26         Configuration config=new Configuration().configure();
    27         //获取注册服务对象(该对象中包含hibernate.cfg.xml中的<properties>和<maping>信息
    28         ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
    29         //获取sessionFactory对象,通过sessionFactory对象读取hibernate.cfg.xml文档信息,并通过<mapping>标签加载hbm.xml文件信息
    30         sessionFactory=config.buildSessionFactory(serviceRegistry);
    31     }
    32     
    33     @Test
    34     public void test3(){
    35         //通过sessionFactory对象获取session对象
    36         session=sessionFactory.openSession();
    37         //通过session对象开启事务,并且返回事务(transaction)对象
    38         transaction=session.beginTransaction();    
    39         
    40         //创建HQL语句用于后面的查询需要
    41         //查询所有记录的sid和sname信息(hql语句)
    42         String hql=" select sid,sname,sgender from Students2";
    43         
    44         //创建多条记录查询对象query1
    45         Query query=session.createQuery(hql);
    46         
    47         /*
    48          * 相同session对象,相同query对象,查询相同的对象
    49          */
    50         List<Object[]> list=query.list();
    51         for (Object[] objects : list) {
    52             System.out.println("学号:"+objects[0]+" 姓名:"+objects[1]+" 性别:"+objects[2]);
    53         }
    54         
    55         List<Object[]> list1=query.list();
    56         for (Object[] objects : list1) {
    57             System.out.println("学号:"+objects[0]+" 姓名:"+objects[1]+" 性别:"+objects[2]);
    58         }
    59     }
    60     
    61     @After
    62     public void destory(){
    63         transaction.commit();
    64         //关闭开启的资源
    65         if(session!=null){
    66             session.close();
    67         }
    68         if(sessionFactory!=null){
    69             sessionFactory.close();
    70         }
    71     }
    72 }

    运行结果:

    Hibernate: 
        select
            students2x0_.SID as col_0_0_,
            students2x0_.SNAME as col_1_0_,
            students2x0_.SGENDER as col_2_0_ 
        from
            STUDENTS2 students2x0_
    学号:1 姓名:小美 性别:女
    学号:2 姓名:小泽 性别:男
    学号:3 姓名:小敏 性别:女
    Hibernate: 
        select
            students2x0_.SID as col_0_0_,
            students2x0_.SNAME as col_1_0_,
            students2x0_.SGENDER as col_2_0_ 
        from
            STUDENTS2 students2x0_
    学号:1 姓名:小美 性别:女
    学号:2 姓名:小泽 性别:男
    学号:3 姓名:小敏 性别:女

    2)没有select子句

     1 package com.third;
     2 
     3 import java.awt.event.FocusEvent;
     4 import java.util.Iterator;
     5 import java.util.List;
     6 
     7 import org.hibernate.Query;
     8 import org.hibernate.Session;
     9 import org.hibernate.SessionFactory;
    10 import org.hibernate.Transaction;
    11 import org.hibernate.cfg.Configuration;
    12 import org.hibernate.service.ServiceRegistry;
    13 import org.hibernate.service.ServiceRegistryBuilder;
    14 import org.junit.After;
    15 import org.junit.Before;
    16 import org.junit.Test;
    17 
    18 import com.third.Dao2.Students2;
    19 import com.third.Dao2.Students2PartInfo;
    20 
    21 public class Test3 {
    22     private static SessionFactory sessionFactory;
    23     private static Session session;
    24     private static Transaction transaction;
    25     @Before
    26     public void init(){
    27         //先获取配置对象,匹配hibernate.cfg.xml文件
    28         Configuration config=new Configuration().configure();
    29         //获取注册服务对象(该对象中包含hibernate.cfg.xml中的<properties>和<maping>信息
    30         ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
    31         //获取sessionFactory对象,通过sessionFactory对象读取hibernate.cfg.xml文档信息,并通过<mapping>标签加载hbm.xml文件信息
    32         sessionFactory=config.buildSessionFactory(serviceRegistry);
    33     }
    34     
    35     @Test
    36     public void test3(){
    37         //通过sessionFactory对象获取session对象
    38         session=sessionFactory.openSession();
    39         //通过session对象开启事务,并且返回事务(transaction)对象
    40         transaction=session.beginTransaction();    
    41         
    42         String hql="from Students2";
    43         Query query=session.createQuery(hql);
    44         List<Students2> stu=query.list();
    45         for (Students2 stu1 : stu) {
    46             System.out.println("学号:"+stu1.getSid()+" 姓名:"+stu1.getSname()+" 性别:"+stu1.getSgender());
    47         }
    48         List<Students2> stu2=query.list();
    49         for (Students2 stu3 : stu2) {
    50             System.out.println("学号:"+stu3.getSid()+" 姓名:"+stu3.getSname()+" 性别:"+stu3.getSgender());
    51         }
    52         
    53         
    54     }
    55     
    56     @After
    57     public void destory(){
    58         transaction.commit();
    59         //关闭开启的资源
    60         if(session!=null){
    61             session.close();
    62         }
    63         if(sessionFactory!=null){
    64             sessionFactory.close();
    65         }        
    66     }    
    67 }

    运行结果:

    Hibernate: 
        select
            students2x0_.SID as SID1_1_,
            students2x0_.SNAME as SNAME2_1_,
            students2x0_.SGENDER as SGENDER3_1_ 
        from
            STUDENTS2 students2x0_
    学号:1 姓名:小美 性别:女
    学号:2 姓名:小泽 性别:男
    学号:3 姓名:小敏 性别:女
    Hibernate: 
        select
            students2x0_.SID as SID1_1_,
            students2x0_.SNAME as SNAME2_1_,
            students2x0_.SGENDER as SGENDER3_1_ 
        from
            STUDENTS2 students2x0_
    学号:1 姓名:小美 性别:女
    学号:2 姓名:小泽 性别:男
    学号:3 姓名:小敏 性别:女

    分析:相同session,甚至相同query对象情况下,查询相同的对象,hibernate解析的SQL语句在数据库执行了两次。

    很明显能看出:session.createQuery(hql).list()方法,不会使用缓存。

    (2)以迭代的方式返回查询结果

    代码示例:

      1 package com.third;
      2 
      3 import java.util.Iterator;
      4 import java.util.List;
      5 
      6 import org.hibernate.Query;
      7 import org.hibernate.Session;
      8 import org.hibernate.SessionFactory;
      9 import org.hibernate.Transaction;
     10 import org.hibernate.cfg.Configuration;
     11 import org.hibernate.service.ServiceRegistry;
     12 import org.hibernate.service.ServiceRegistryBuilder;
     13 import org.junit.After;
     14 import org.junit.Before;
     15 import org.junit.Test;
     16 
     17 import com.third.Dao2.Students2;
     18 import com.third.Dao2.Students2PartInfo;
     19 
     20 public class Test3 {
     21     private static SessionFactory sessionFactory;
     22     private static Session session;
     23     private static Transaction transaction;
     24     @Before
     25     public void init(){
     26         //先获取配置对象,匹配hibernate.cfg.xml文件
     27         Configuration config=new Configuration().configure();
     28         //获取注册服务对象(该对象中包含hibernate.cfg.xml中的<properties>和<maping>信息
     29         ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
     30         //获取sessionFactory对象,通过sessionFactory对象读取hibernate.cfg.xml文档信息,并通过<mapping>标签加载hbm.xml文件信息
     31         sessionFactory=config.buildSessionFactory(serviceRegistry);
     32     }
     33     
     34     @Test
     35     public void test3(){
     36         //通过sessionFactory对象获取session对象
     37         session=sessionFactory.openSession();
     38         //通过session对象开启事务,并且返回事务(transaction)对象
     39         transaction=session.beginTransaction();    
     40         
     41         /*
     42          * 这里我们执行带有select子句的查询
     43          */
     44         //创建HQL语句用于后面的查询需要
     45         //查询所有记录的sid和sname信息(hql语句)
     46         String hql=" select sid,sname,sgender from Students2";
     47         
     48         //创建多条记录查询对象query1
     49         Query query=session.createQuery(hql);
     50         System.out.println("*************带有select子句的查询*********************");
     51         Iterator it=query.iterate();
     52         while(it.hasNext()){
     53             Object[] obj=(Object[])it.next();
     54             System.out.println("学号:"+obj[0]+" 姓名:"+obj[1]+" 性别:"+obj[2]);
     55         }
     56         //在同一session同一query1对象下查询相同的对象
     57         System.out.println("同一个session并且同一个query对象下查询相同对象:");
     58         Iterator it2=query.iterate();
     59         while(it2.hasNext()){
     60             Object[] obj=(Object[])it2.next();
     61             System.out.println("学号:"+obj[0]+" 姓名:"+obj[1]+" 性别:"+obj[2]);
     62         }
     63         System.out.println("**************不带select子句的查询**********************");
     64         /*
     65          * 这里我们执行不带有select子句的查询
     66          */
     67         Session session1=sessionFactory.openSession();
     68         String hql1="from Students2";
     69         Query query1=session.createQuery(hql1);
     70         Iterator<Students2> it1=query1.iterate();
     71         while(it1.hasNext()){
     72             Students2 stu=it1.next();
     73             System.out.println("学号:"+stu.getSid()
     74             +"  姓别:"+stu.getSgender()+"  姓名:"+stu.getSname());
     75         }
     76         //在同一session同一query1对象下查询相同的对象
     77         System.out.println("在同一session同一query1对象下查询相同的对象:");
     78         Iterator<Students2> it3=query1.iterate();
     79         while(it3.hasNext()){
     80             Students2 stu=it3.next();
     81             System.out.println("学号:"+stu.getSid()
     82             +"  姓别:"+stu.getSgender()+"  姓名:"+stu.getSname());
     83         }
     84         //在同一个session但是不是一个query对象下查询相同对象
     85         System.out.println("在同一个session但是不是一个query对象下查询相同对象:");
     86          Query query2=session.createQuery(hql1);
     87             Iterator<Students2> it4=query2.iterate();
     88             while(it4.hasNext()){
     89                 Students2 stu=it4.next();
     90                 System.out.println("学号:"+stu.getSid()
     91                 +"  姓别:"+stu.getSgender()+"  姓名:"+stu.getSname());
     92             }
     93         //在不同的session中,查询相同的对象
     94             System.out.println("在不同的session中,查询相同的对象:");
     95             Session session2=sessionFactory.openSession();
     96             String hql2="from Students2";
     97             Query query3=session2.createQuery(hql1);
     98             Iterator<Students2> it5=query3.iterate();
     99             while(it5.hasNext()){
    100                 Students2 stu=it5.next();
    101                 System.out.println("学号:"+stu.getSid()
    102                 +"  姓别:"+stu.getSgender()+"  姓名:"+stu.getSname());
    103             }
    104     }
    105     
    106     @After
    107     public void destory(){
    108         transaction.commit();
    109         //关闭开启的资源
    110         if(session!=null){
    111             session.close();
    112         }
    113         if(sessionFactory!=null){
    114             sessionFactory.close();
    115         }
    116     }
    117 }

    运行结果:

    *************带有select子句的查询*********************
    Hibernate: 
        select
            students2x0_.SID as col_0_0_,
            students2x0_.SNAME as col_1_0_,
            students2x0_.SGENDER as col_2_0_ 
        from
            STUDENTS2 students2x0_
    学号:1 姓名:小美 性别:女
    学号:2 姓名:小泽 性别:男
    学号:3 姓名:小敏 性别:女
    同一个session并且同一个query对象下查询相同对象:
    Hibernate: 
        select
            students2x0_.SID as col_0_0_,
            students2x0_.SNAME as col_1_0_,
            students2x0_.SGENDER as col_2_0_ 
        from
            STUDENTS2 students2x0_
    学号:1 姓名:小美 性别:女
    学号:2 姓名:小泽 性别:男
    学号:3 姓名:小敏 性别:女
    **************不带select子句的查询**********************
    Hibernate: 
        select
            students2x0_.SID as col_0_0_ 
        from
            STUDENTS2 students2x0_
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:1  姓别:女  姓名:小美
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:2  姓别:男  姓名:小泽
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:3  姓别:女  姓名:小敏
    在同一session同一query1对象下查询相同的对象:
    Hibernate: 
        select
            students2x0_.SID as col_0_0_ 
        from
            STUDENTS2 students2x0_
    学号:1  姓别:女  姓名:小美
    学号:2  姓别:男  姓名:小泽
    学号:3  姓别:女  姓名:小敏
    在同一个session但是不是一个query对象下查询相同对象:
    Hibernate: 
        select
            students2x0_.SID as col_0_0_ 
        from
            STUDENTS2 students2x0_
    学号:1  姓别:女  姓名:小美
    学号:2  姓别:男  姓名:小泽
    学号:3  姓别:女  姓名:小敏
    在不同的session中,查询相同的对象:
    Hibernate: 
        select
            students2x0_.SID as col_0_0_ 
        from
            STUDENTS2 students2x0_
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:1  姓别:女  姓名:小美
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:2  姓别:男  姓名:小泽
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:3  姓别:女  姓名:小敏

    分析:以迭代器方式返回的查询,执行我们分成使用select子句和没有使用select子句的查询:

    1)使用了select子句的查询,是不会使用缓存的

    2)不使用select子句的查询,情况可以分为在同一个session下和不同的session下查询相同的对象。在同一个session下,第一次查询缓存中不存在的对象时,会先到数据库中查询要查对象的主键,然后依靠主键使用where子句限定主键,然后一一按照主键到数据库中执行SQL语句查询对象;再次查询相同对象时,会现在缓存中查询对象的编号,找到相同编号的返回,找不到的,再到数据库去按照编号查找。在不同session下,缓存一般不能使用。

    二、一级缓存相关介绍

    1、hibernate一级缓存也称为“会话级缓存”、“session缓存”。

    2、一级缓存的生命周期和session相同,session销毁,缓存也销毁。

    3、一级缓存数据的使用范围,或者说是作用域为当前会话。

    4、hibernate一级缓存的API

    一级缓存无法取消,用两个方法管理。

    evict():用于将某个对象从session中的一级缓存中清除。

    clear():用于将一级缓存中的对象全部清除。

     1 package com.third;
     2 
     3 import org.hibernate.Session;
     4 import org.hibernate.SessionFactory;
     5 import org.hibernate.Transaction;
     6 import org.hibernate.cfg.Configuration;
     7 import org.hibernate.service.ServiceRegistry;
     8 import org.hibernate.service.ServiceRegistryBuilder;
     9 import org.junit.After;
    10 import org.junit.Before;
    11 import org.junit.Test;
    12 
    13 import com.third.Dao2.Students2;
    14 
    15 public class Test3 {
    16     private static SessionFactory sessionFactory;
    17     private static Session session;
    18     private static Transaction transaction;
    19     @Before
    20     public void init(){
    21         //先获取配置对象,匹配hibernate.cfg.xml文件
    22         Configuration config=new Configuration().configure();
    23         //获取注册服务对象(该对象中包含hibernate.cfg.xml中的<properties>和<maping>信息
    24         ServiceRegistry serviceRegistry=new ServiceRegistryBuilder().applySettings(config.getProperties()).buildServiceRegistry();
    25         //获取sessionFactory对象,通过sessionFactory对象读取hibernate.cfg.xml文档信息,并通过<mapping>标签加载hbm.xml文件信息
    26         sessionFactory=config.buildSessionFactory(serviceRegistry);
    27     }
    28     
    29     @Test
    30     public void test3(){
    31         //通过sessionFactory对象获取session对象
    32         session=sessionFactory.openSession();
    33         //通过session对象开启事务,并且返回事务(transaction)对象
    34         transaction=session.beginTransaction();    
    35         
    36         Students2 stu1=(Students2) session.get(Students2.class, 1);
    37         Students2 stu2=(Students2) session.get(Students2.class, 2);
    38         Students2 stu3=(Students2) session.get(Students2.class, 3);
    39         
    40         System.out.println("第一遍查询:");
    41         System.out.println("学号:"+stu1.getSid()+" 姓名:"+stu1.getSname()+" 性别:"+stu1.getSgender());
    42         System.out.println("学号:"+stu2.getSid()+" 姓名:"+stu2.getSname()+" 性别:"+stu2.getSgender());
    43         System.out.println("学号:"+stu3.getSid()+" 姓名:"+stu3.getSname()+" 性别:"+stu3.getSgender());
    44         
    45         //先使用evict()方法,然后在查询相同session下之前查过的对象
    46         System.out.println("先使用evict()方法,然后在查询相同session下之前查过的对象:");
    47         session.evict(stu1);
    48         Students2 stu4=(Students2) session.get(Students2.class, 1);
    49         System.out.println("学号:"+stu4.getSid()+" 姓名:"+stu4.getSname()+" 性别:"+stu4.getSgender());
    50         
    51         //使用clear()方法,然后再查询相同session下之前查过的对象。
    52         System.out.println("使用clear()方法,然后再查询相同session下之前查过的对象:");
    session.clear();
    53 Students2 stu5=(Students2) session.get(Students2.class, 1); 54 Students2 stu6=(Students2) session.get(Students2.class, 2); 55 Students2 stu7=(Students2) session.get(Students2.class, 3); 56 57 System.out.println("学号:"+stu5.getSid()+" 姓名:"+stu5.getSname()+" 性别:"+stu5.getSgender()); 58 System.out.println("学号:"+stu6.getSid()+" 姓名:"+stu6.getSname()+" 性别:"+stu6.getSgender()); 59 System.out.println("学号:"+stu7.getSid()+" 姓名:"+stu7.getSname()+" 性别:"+stu7.getSgender()); 60 } 61 62 @After 63 public void destory(){ 64 transaction.commit(); 65 //关闭开启的资源 66 if(session!=null){ 67 session.close(); 68 } 69 if(sessionFactory!=null){ 70 sessionFactory.close(); 71 } 72 } 73 }

    运行结果:

    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    第一遍查询:
    学号:1 姓名:小美 性别:女
    学号:2 姓名:小泽 性别:男
    学号:3 姓名:小敏 性别:女
    先使用evict()方法,然后在查询相同session下之前查过的对象:
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:1 姓名:小美 性别:女
    使用clear()方法,然后再查询相同session下之前查过的对象:
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    Hibernate: 
        select
            students2x0_.SID as SID1_1_0_,
            students2x0_.SNAME as SNAME2_1_0_,
            students2x0_.SGENDER as SGENDER3_1_0_ 
        from
            STUDENTS2 students2x0_ 
        where
            students2x0_.SID=?
    学号:1 姓名:小美 性别:女
    学号:2 姓名:小泽 性别:男
    学号:3 姓名:小敏 性别:女

    三、总结:

    (1)一级缓存的数据的作用范围为一个session,缓存会随着session的销毁而销毁。

    (2)其中通过get()、load()、和以Iterator(迭代器)方式返回无select子句查询都会使用到缓存,但是通过以list方式和Iterator(迭代器)方式返回的有select子句的查询不会使用缓存。

    (3)其中以Iterator(迭代器)方式返回的hibernate查询都是先从数据库中查询对象的编号,然后到缓存中查找匹配的编号,找到了直接返回,找不到通过where子句限定以编号去数据库中查找,然后返回。

    一级缓存查询的流程图:

  • 相关阅读:
    FZU 2112 并查集、欧拉通路
    HDU 5686 斐波那契数列、Java求大数
    Codeforces 675C Money Transfers 思维题
    HDU 5687 字典树插入查找删除
    HDU 1532 最大流模板题
    HDU 5384 字典树、AC自动机
    山科第三届校赛总结
    HDU 2222 AC自动机模板题
    HDU 3911 线段树区间合并、异或取反操作
    CodeForces 615B Longtail Hedgehog
  • 原文地址:https://www.cnblogs.com/xiaotiaosi/p/6498122.html
Copyright © 2011-2022 走看看