Hibernate的二级缓存
一、缓存概述
缓存(Cache): 计算机领域非常通用的概念。它介于应用程序和永久性数据存储源(如硬盘上的文件或者数据库)之间,其作用是降低应用程序直接读写永久性数据存储源的频率,从而提高应用的运行性能。缓存中的数据是数据存储源中数据的拷贝。缓存的物理介质通常是内存
hibernate中提供了两个级别的缓存
第一级别的缓存是 Session 级别的缓存,它是属于事务范围的缓存。这一级别的缓存由 hibernate 管理的,一般情况下无需进行干预
第二级别的缓存是 SessionFactory 级别的缓存,它是属于进程范围的缓存
Hibernate 的缓存可以分为两类:
内置缓存: Hibernate 自带的, 不可卸载. 通常在 Hibernate 的初始化阶段, Hibernate 会把映射元数据和预定义的 SQL 语句放到 SessionFactory 的缓存中, 映射元数据是映射文件中数据的复制, 而预定义 SQL 语句时 Hibernate 根据映射元数据推到出来的. 该内置缓存是只读的.
外置缓存(二级缓存): 一个可配置的缓存插件. 在默认情况下, SessionFactory 不会启用这个缓存插件. 外置缓存中的数据是数据库数据的复制, 外置缓存的物理介质可以是内存或硬盘
二、理解二级缓存的并发访问策略
三、配置进程范围内的二级缓存(配置ehcache缓存)
1 拷贝ehcache-1.5.0.jar到当前工程的lib目录下
依赖 backport-util-concurrent 和 commons-logging
2 开启二级缓存
1
|
< property name = "hibernate.cache.use_second_level_cache" >true</ property > |
3 要指定缓存的供应商
1
2
|
< property name = "hibernate.cache.provider_class" > org.hibernate.cache.EhCacheProvider</ property > |
4 指定使用二级缓存的类
方法一 在使用类的*.hbm.xml配置
选择需要使用二级缓存的持久化类, 设置它的二级缓存的并发访问策略, <class> 元素的 cache 子元素表明 Hibernate 会缓存对象的简单属性, 但不会缓存集合属性, 若希望缓存集合属性中的元素, 必须在 <set> 元素中加入 <cache> 子元素
方法二 在hibernate.cfg.xml文件中配置(建议)
1
2
3
4
5
6
7
8
|
<!-- 指定使用二级缓存的类 放在maping下面 --> <!-- 配置类级别的二级缓存 --> < class-cache class = "com.sihai.c3p0.Customer" usage = "read-write" /> < class-cache class = "com.sihai.c3p0.Order" usage = "read-write" /> <!-- 配置集合级别的二级缓存 --> < collection-cache collection = "com.sihai.c3p0.Customer.orders" usage = "read-write" /> |
5 配置ehcache默认的配置文件ehcache.xml(名字固定)(放在类路径下)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
< ehcache xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation = "../config/ehcache.xsd" > < diskStore path = "c:/ehcache" /> < defaultCache maxElementsInMemory = "5" eternal = "false" timeToIdleSeconds = "120" timeToLiveSeconds = "120" overflowToDisk = "true" maxElementsOnDisk = "10000000" diskPersistent = "false" diskExpiryThreadIntervalSeconds = "120" memoryStoreEvictionPolicy = "LRU" /> </ ehcache > |
四、 测试
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
|
package com.sihai.hibernate3.test; import java.util.Iterator; import java.util.List; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import com.sihai.hibernate3.demo1.Customer; import com.sihai.hibernate3.demo1.Order; import com.sihai.utils.HibernateUtils; public class HibernateTest6 { @Test // 查询缓存的测试 public void demo9(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); Query query = session.createQuery( "select c.cname from Customer c" ); // 使用查询缓存: query.setCacheable( true ); query.list(); tx.commit(); session = HibernateUtils.getCurrentSession(); tx = session.beginTransaction(); query = session.createQuery( "select c.cname from Customer c" ); query.setCacheable( true ); query.list(); tx.commit(); } @SuppressWarnings ( "unused" ) @Test // 更新时间戳 public void demo8(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer. class , 2 ); session.createQuery( "update Customer set cname = '奶茶' where cid = 2" ).executeUpdate(); tx.commit(); session = HibernateUtils.getCurrentSession(); tx = session.beginTransaction(); Customer customer2 = (Customer) session.get(Customer. class , 2 ); tx.commit(); } @SuppressWarnings ( "all" ) @Test // 将内存中的数据写到硬盘 public void demo7(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); List<Order> list = session.createQuery( "from Order" ).list(); tx.commit(); } @Test // 一级缓存的更新会同步到二级缓存: public void demo6(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer. class , 1 ); customer.setCname( "芙蓉" ); tx.commit(); session = HibernateUtils.getCurrentSession(); tx = session.beginTransaction(); Customer customer2 = (Customer) session.get(Customer. class , 1 ); tx.commit(); } @SuppressWarnings ( "unchecked" ) @Test // iterate()方法可以查询所有信息. // iterate方法会发送N+1条SQL查询.但是会使用二级缓存的数据 public void demo5(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // N+1条SQL去查询. Iterator<Customer> iterator = session.createQuery( "from Customer" ).iterate(); while (iterator.hasNext()){ Customer customer = iterator.next(); System.out.println(customer); } tx.commit(); session = HibernateUtils.getCurrentSession(); tx = session.beginTransaction(); iterator = session.createQuery( "from Customer" ).iterate(); while (iterator.hasNext()){ Customer customer = iterator.next(); System.out.println(customer); } tx.commit(); } @SuppressWarnings ( "unchecked" ) @Test // 查询所有.Query接口的list()方法. // list()方法会向二级缓存中放数据,但是不会使用二级缓存中的数据. public void demo4(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 查询所有客户: // list方法会向二级缓存中放入数据的. List<Customer> list = session.createQuery( "from Customer" ).list(); for (Customer customer : list) { System.out.println(customer.getCname()); } tx.commit(); session = HibernateUtils.getCurrentSession(); tx = session.beginTransaction(); // Customer customer = (Customer) session.get(Customer.class, 1);// 没有发生SQL ,从二级缓存获取的数据. // list()方法没有使用二级缓存的数据. list = session.createQuery( "from Customer" ).list(); for (Customer customer : list) { System.out.println(customer.getCname()); } tx.commit(); } @Test // 二级缓存的集合缓冲区特点: public void demo3(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); Customer customer = (Customer) session.get(Customer. class , 1 ); // 查询客户的订单. System.out.println( "订单的数量:" +customer.getOrders().size()); tx.commit(); session = HibernateUtils.getCurrentSession(); tx = session.beginTransaction(); Customer customer2 = (Customer) session.get(Customer. class , 1 ); // 查询客户的订单. System.out.println( "订单的数量:" +customer2.getOrders().size()); tx.commit(); } @SuppressWarnings ( "unused" ) @Test // 配置二级缓存的情况 public void demo2(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); Customer customer1 = (Customer) session.get(Customer. class , 1 ); // 发送SQL. Customer customer2 = (Customer) session.get(Customer. class , 1 ); // 不发送SQL. System.out.println(customer1 == customer2); tx.commit(); session = HibernateUtils.getCurrentSession(); tx = session.beginTransaction(); Customer customer3 = (Customer) session.get(Customer. class , 1 ); // 不发送SQL. Customer customer4 = (Customer) session.get(Customer. class , 1 ); // 不发送SQL. System.out.println(customer3 == customer4); tx.commit(); } @SuppressWarnings ( "unused" ) @Test // 没有配置二级缓存的情况 public void demo1(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); Customer customer1 = (Customer) session.get(Customer. class , 1 ); // 发送SQL. Customer customer2 = (Customer) session.get(Customer. class , 1 ); // 不发送SQL. tx.commit(); session = HibernateUtils.getCurrentSession(); tx = session.beginTransaction(); Customer customer3 = (Customer) session.get(Customer. class , 1 ); // 发送SQL. tx.commit(); } } |
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:http://blog.csdn.net/sihai12345/article/details/70245469