• 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子句限定以编号去数据库中查找,然后返回。

    一级缓存查询的流程图:

    标签: 框架, Hibernate
  • 相关阅读:
    php通过ip获取地理位置的方法
    python程序怎么运行起来的
    php cURL学习 一个post提交反馈的小例子
    如何运行Python程序
    python初学者的建议
    php5.4新特性实践
    php中json_encode与json_decode注意事项
    Apanta安装Emmet(Zencoding)
    office 2013 电话激活步骤
    js中encodeURI()与encodeURIComponent()区别
  • 原文地址:https://www.cnblogs.com/smallfa/p/6512002.html
Copyright © 2020-2023  润新知