Dict.CN 在线词典, 英语学习, 在线翻译 ------------- MyGitee 朱秋贵内科诊所 My腾云code

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
posted @ 2017-03-06 21:14  cn2024  阅读(257)  评论(0编辑  收藏  举报