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子句限定以编号去数据库中查找,然后返回。
一级缓存查询的流程图: