该用户从未签到
需要启动二级缓存,二级缓存的scope是sessionFactory。也就是说二级缓存的数据可以在由相同SessionFactory创建的多个Session中重用。
5 L2 |/ V0 V8 n$ E; W , N( |; a3 X: E6 m0 \7 r9 e
首先,要在hibernate .cfg.xml中设置一个cache Provider,hibernate支持多个cache实现,有EHCache,OSCache等。在非分布式环境中可以选择默认的EHCache。添加ehcahe jar( b5 L8 e, U) M L
<dependency>
2 O/ n: N( O9 F) ?" T! w6 N <groupId>org.hibernate</groupId>. Y! A; a4 x# y) y3 K
<artifactId>hibernate-ehcache</artifactId>
0 i; o" I& I: V- ~# d8 q <version>4.3.5.Final</version>/ O6 e3 {! ?8 J0 I' F& n
</dependency> 复制代码 <hibernate-configuration>0 e' ?2 E" O; ]0 H3 k j
<session-factory>
0 g! N2 ?, ]* d; ^8 U- ?3 _ <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
" ?9 S/ k& W0 F* Y+ Z <property name="connection.url">jdbc:mysql://localhost/test</property>
9 W1 ]; P/ h. V% j: i6 G/ B <property name="connection.username">root</property>) l7 A8 t W$ U
<property name="connection.password"></property>
2 V0 Z# p0 w) \ G3 K) t5 p" K <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>; S6 I1 J0 O$ y5 C% M# k1 f( ^
<property name="hibernate.show_sql">true</property>
0 X- { x: D! u4 j- w <property name="hibernate.hbm2ddl.auto">update</property>
& [3 B" e0 v5 H <property name="hibernate.generate_statistics">true</property>/ d1 w0 @3 m6 h8 X! Z5 m
<property name="hibernate.cache.region.factory_class">
+ s s* X6 `/ a org.hibernate.cache.ehcache.EhCacheRegionFactory# h4 }1 \, f- Z6 i# @5 J7 J
</property>, K# t8 h4 J/ z3 G$ `8 p9 S; I1 w" ~
<mapping class="com.xinglongjian.entity.hbm.Book2"/>
6 c1 P0 G3 y+ n1 ~/ n- X0 x </hibernate-configuration> 复制代码 8 J2 a5 ]" R! ~! T5 ?0 k
第二,通过ehcache.xml配置EHCache,该文件放置于classpath的根目录下。可以在该配置文件中设置将不同的对象存储在不同的regions。<ehcache>
0 y! W) [4 d/ z <diskStore path="c:/data/ehcache"/>
5 D* ^' p$ X/ W+ C6 o1 H <defaultCache
4 E6 J2 t# M! @) ~& |- \6 n2 r* ? maxElementsInMemory="10"* k3 s {, w6 f' p. m3 T, s
eternal="false"3 \7 O: X i0 L: D8 M9 y
overflowToDisk="true"' l7 T! f( ]3 B/ @: X! N. M6 y
timeToIdleSeconds="120"' N6 _6 O. p: j9 z4 F+ c! w
timeToLiveSeconds="120"7 j$ D& F" w5 Y! e7 q/ V
diskPersistent="false"8 Z1 Y$ c0 t/ m3 n4 x
diskExpiryThreadIntervalSeconds="120"/>
$ G' _& c0 M J) I* D, w <cache name="com.xinglongjian.entity.hbm.Book" maxElementsInMemory="10" eternal="false" " F' {' E6 ~* G6 U6 i0 _" ?
overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskPersistent="false"/>+ \# k6 N9 r/ L& p; n. [- f
</ehcache> 复制代码 第三,设置持久化类@Entity
. \2 \. L% M% m% c& b ] @Cacheable& O o- _( V( a
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY,region="com.xinglongjian.entity.hbm.Book")% |1 T: y# O# V) N
public class Book2 {& I& _" g' p4 K& l) r: ?
@Id
% X6 S6 ?# o* F* D" ^3 F @GeneratedValue# `6 B/ ~$ S! l6 N; t+ x2 N; a
private int id;
; k, J+ `1 S' A& @1 t# L private String title;2 D! O4 c: n! G9 |% C; a# q: Q, f
public String getTitle() {
' E3 l$ r, s) w. G c return title;
5 a* U+ M4 b9 f+ y! N }9 W+ K7 y. C# }( i8 V
public void setTitle(String title) {0 K& R. R( Z# G2 p' J/ Q
this.title = title;- p# O5 U) M T$ w4 p
}+ o% [6 y k" A/ S* Z, x# F- Q: p V
public int getId() {
/ g" r7 \( [# M; l! ~ return id;
" F& Z( \) \4 l$ n- K }7 }4 i1 E2 G5 D$ U9 [9 q7 v
public void setId(int id) {
7 m, d, G# E# C this.id = id;# o N8 Q1 v" P6 j4 q% o9 h
}
) t9 H; E. v1 W @Override+ L' f$ F8 P0 ^* W; r
public int hashCode() {
, B' s! q$ u3 P( B1 T+ @+ Q final int prime = 31;
; V$ e1 H1 ]: X- { int result = 1;8 ^4 t) ]2 C. l
result = prime * result + id;4 \/ U/ F! Y, c R/ k# h
result = prime * result + ((title == null) ? 0 : title.hashCode());7 s) p+ I5 z" V- R
return result;
8 k: N/ D2 C7 ]9 n' c' V. @ }: N3 U1 q2 D! Z2 P
@Override
) z" o8 Q) W% @4 P0 A8 t) c public boolean equals(Object obj) {+ Y1 Z ?" d. ~ o) x. J, ^/ ^
if (this == obj)+ T9 B4 O3 W* ~1 q) D7 |3 X
return true;4 E' f$ P- n6 Q
if (obj == null)
9 k$ X- n' J, f$ p3 W! o5 f/ V return false;
! ~$ q- M9 g- ~, D! J if (getClass() != obj.getClass())1 k5 L( Y' S5 j6 {
return false;
: J- `9 @$ S: a, S" p' r Book2 other = (Book2) obj;
, R4 H$ e+ T$ j" ^1 c( Q) d! A/ B: i if (id != other.id)
* x5 }! q; L) h1 b$ N% F# U return false;) I |9 @+ x' n8 Z/ I) g6 F
if (title == null) {0 Q/ H( p- h& M0 O9 |5 \* U8 |8 c5 m! |
if (other.title != null)2 [8 b2 i0 F0 n9 x% k
return false;
6 k9 M3 s- e5 m3 y } else if (!title.equals(other.title))6 d0 y- i2 K% q3 b( ]+ ~
return false;
" a& ~3 U; _- F; l, c return true;5 I% ]& `% ^ i' q
}
/ r8 G% e( z6 z8 z- P
$ a2 `1 V4 A$ z* V } 复制代码 二级缓存的持久化类必须实现equals方法。! {4 j7 t4 Z) v) w+ a W# M$ u) B
- B# u* \4 a9 ~8 f1 W
只有在SELECT时才会缓存。 a/ h. Q3 K- w* M& R5 K
/ U+ X/ }0 E, P1 R9 C
在同一个session里,查询2个不同的对象,会缓存2次,Session sess=sf.openSession();' H8 L* Q: a G) j$ k
Book2 b=(Book2) sess.get(Book2.class, 17);$ g( B# T+ V- j4 Q* O0 z) A- t, l
System.out.println(b);
, t4 s6 O' ~+ _ X assertEquals("spring Recipes", b.getTitle());
1 M8 g; k: U" o3 Z) i Book2 b3=(Book2) sess.get(Book2.class, 18);0 t0 r6 r7 @" }/ t8 F4 a( d, Q
assertEquals("dfad", b3.getTitle());
/ C8 S& m7 D' D) m( b3 E sess.close();
' R& Z# i |/ y" H8 q' B slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
% H. p# B1 |6 h$ Q- I' W/ \3 ]- } e System.out.println(slcs); 复制代码 结果SecondLevelCacheStatistics[hitCount=0,missCount=2,putCount=2,elementCountInMemory=2,elementC( q, s9 M# I& x& w8 [
ountOnDisk=0,sizeInMemory=3948] 复制代码 ( W4 { Q( c; _# G ^$ K: L
在同一个session里,查询相同的对象,会先查询一级缓存,一级缓存中有就不会查询二级缓存。Session sess1=sf.openSession();& |6 S7 V# B3 c3 C6 M+ i2 G
Book2 b1=(Book2) sess1.get(Book2.class, 17);
! R( Q! e; ]9 c! T! y/ V5 v A' @8 L System.out.println(b);
* t% F* B. {1 |# k* ]1 D Book2 b2=(Book2) sess1.get(Book2.class, 17);( ~3 {# g m: ~6 i6 ~$ n7 G' ~2 U3 ]# `
assertEquals("Spring Recipes", b1.getTitle());, z# X c& W0 H* _
assertEquals("Spring Recipes", b2.getTitle());/ N1 x2 Q, X1 D p6 P& Q1 D
slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
! e; m b1 u% A6 W3 i9 b& r System.out.println(slcs); 复制代码 结果,在新的session中,一级缓存不可用,就会使用二级缓存。SecondLevelCacheStatistics[hitCount=1,missCount=2,putCount=2,elementCountInMemory=2,elementC
8 V l$ q" B# Q0 d ountOnDisk=0,sizeInMemory=3948] 复制代码 完整测试逻辑@Test m8 S6 d- \- p# ?
public void test2LCache()
8 F6 w9 P0 j1 `- U& H' k" d {: O! E; j, |. p0 ]8 Z8 }
Statistics stat=sf.getStatistics();//获取stat对象. L8 W, N+ ~2 P" k
Session sess=sf.openSession();2 A: T Q4 o7 R7 `4 ]' c& O. S
Transaction tx=sess.beginTransaction(); T$ j4 S% F2 q2 I) a
8 V/ @ d2 r- A/ l. a
//存储对象,此时不会放到缓存中7 ]+ Y9 i- W4 E
System.out.println("--------------存储对象---------------------------------");
- f% k$ ^' |+ r: M# m2 V* | Book2 book=new Book2();
- d/ Y. }+ T1 Q* m9 B* D book.setTitle("Spring Recipes");9 Z6 g k G: U/ V; r1 K* \
sess.saveOrUpdate(book);
4 ?/ O* l, s" A) w* ` tx.commit();1 S9 n3 H* U( _8 a) N' J$ k
sess.close();3 c! L' x: O6 N6 ~3 Y2 E$ ~
System.out.println(book);
$ D# {3 y) W( [9 Z SecondLevelCacheStatistics slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
1 K" h* f2 n. d: ?7 E System.out.println(slcs);
- v" e- S6 [: k" ^, S E/ k Cache cache=sf.getCache();* v3 v( J% ` P" F" ~2 a8 e
System.out.println(cache);
2 P) H' w' t. f4 R% d1 d cache.evictAllRegions();//从所有region中获取数据
" a! e% p c4 b+ s Map map=slcs.getEntries();
u9 K7 a. P$ o7 n System.out.println("Cache entries:"+map.size());/ ~2 [: Z" T4 N7 W- a' Y2 w
System.out.println("--------------第一次查询后---------------------------------");8 `/ [9 I4 s1 w. W8 W
sess=sf.openSession();
$ J, v7 ^8 D+ i# Q/ I2 c tx=sess.beginTransaction();
( Z( y# K2 Q9 L) k! ` Book2 b1=(Book2) sess.byId(Book2.class).load(book.getId());//第一次查询3 e% e0 T) \# g& i2 s# ]
System.out.println(b1);
& j1 P, N& [% h/ C assertEquals(book, b1);
4 U, V8 S. n1 U" q5 j z' c. z8 r tx.commit();
2 t9 H( T) S3 q( e' h" ^9 ~/ v sess.close();8 g; j; H( R% {9 c
slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");2 i' K& a& i4 R' L0 H
System.out.println(slcs);1 b) j& W9 c& G9 k: J
map=slcs.getEntries();
, F, F- D0 A& a. @( T System.out.println(map.size());& Z8 g! y, A) v$ b8 F0 e: B' {
System.out.println("--------------第二次查询后---------------------------------");1 ~; e4 d8 i$ N% |2 c- [: L
sess=sf.openSession();
$ U4 a" }- r+ e( _4 _8 k tx=sess.beginTransaction(); B ]5 z1 k' q1 p# a4 j
Book2 b2=(Book2) sess.byId(Book2.class).load(book.getId());//第二次查询0 Y4 d2 D' f2 d5 `( q$ ~
System.out.println(b2);
# }& t% Y( a. l! h1 s$ `4 Y. } assertEquals(book, b2);
5 ^- j1 G, o6 _* H3 z. }( | x, g tx.commit();4 o, Z: b! p: c: }8 t
sess.close();7 ~/ A% R E2 E* N! J; y# P
) M6 P% W9 h2 M5 Q% \2 _
slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");( b! g: z E' s; r
System.out.println(slcs); \; @8 z/ Y! j; Q$ C
// this is the initial select. S9 D$ N# [0 @& ~5 A i
assertEquals(stat.getSecondLevelCacheMissCount(), 1); u J# m$ |0 w+ t9 @, N/ n6 [- B" N
// we put one element in the cache from the miss
3 p( P" C3 u) \( U; h assertEquals(stat.getSecondLevelCachePutCount(), 1);2 s, }" [' u( L( a9 i+ Z+ P
// we still didn't hit the cache, because of 1L cache
$ ?6 V4 V. M) z; X- H assertEquals(stat.getSecondLevelCacheHitCount(), 1);
8 Z: s+ a8 e! w& G5 T7 O: D1 u9 K System.out.println("--------------第三次查询后---------------------------------");( J5 I0 o7 k) ^) A; ~3 w
sess=sf.openSession();( D" p2 Y& ?! p& U' k1 D
tx=sess.beginTransaction();4 C% u4 G m% n; Q+ P* D: K
b1=(Book2) sess.byId(Book2.class).load(book.getId());//第三次查询
: c0 _# m& h9 G+ s& L! y; y assertEquals(book, b1);8 y; y+ p# S: @
tx.commit(); J0 j! o: U. x7 |1 x1 ?7 k l4 ^
sess.close();
. t" _$ ~: U, [
6 l8 H0 F# ^* n- a: I# w slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");! O2 R/ u E: y, f% r0 j
System.out.println(slcs);
. g3 v5 Z- C3 c5 a% u2 ^ // same miss count (we should hit now)
! C# {) a( \( K" m. W7 G assertEquals(stat.getSecondLevelCacheMissCount(), 1);" F9 }# J( v( N6 ~
// same put count (we didn't put anything new)
8 n' _+ k! w. C# D8 K assertEquals(stat.getSecondLevelCachePutCount(), 1);5 Z) C: C' X$ ]6 M
// now we hit the 2L cache for load" s8 P& c) Q+ s6 b% j; S* t4 H4 r
assertEquals(stat.getSecondLevelCacheHitCount(), 2);9 v( x+ F2 P A. P
2 t# Z! R% j7 _$ d* b } 复制代码 完整测试结果Hibernate: delete from book2- ` R4 h, G( L7 A$ P' {5 U
--------------存储对象---------------------------------
+ @ P2 b7 i" P( [4 T- b, w6 m Hibernate: insert into Book2 (title) values (?)- q6 ~# ^: d" J! ~
com.xinglongjian.entity.hbm.Book2@521e083b
3 |- v0 J3 Y. ] @; b* } SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=0,elementCountInMemory=0,elementCountOnDisk=0,sizeInMemory=0]
! p, G: b Y+ J2 P9 r# M D7 K org.hibernate.internal.CacheImpl@4830f6" ?; [9 a# T1 X8 C) K
Cache entries:06 h$ y7 i V7 ~5 u- ?, L, r
--------------第一次查询后---------------------------------$ N# K" c, Q5 l3 t
Hibernate: select book2x0_.id as id1_0_0_, book2x0_.title as title2_0_0_ from Book2 book2x0_
5 b) F" ~8 C0 _) G1 R where book2x0_.id=?- T2 g/ i' u- F
com.xinglongjian.entity.hbm.Book2@521e083b
7 o* f# Q8 t" c/ t; {. D SecondLevelCacheStatistics[hitCount=0,missCount=1,putCount=1,elementCountInMemory=1,elementC
2 V A7 d, X1 e3 n2 N4 O ountOnDisk=0,sizeInMemory=1979]
0 L% A( Y- v- _ h6 [ 1
- d) T8 X. x0 A- d+ t5 P --------------第二次查询后---------------------------------
1 e8 r" A7 T4 b5 z com.xinglongjian.entity.hbm.Book2@521e083b
8 a" F4 f# N+ `4 b) k# l SecondLevelCacheStatistics[hitCount=1,missCount=1,putCount=1,elementCountInMemory=1,elementC# x2 J! g* p6 D3 I! {8 S
ountOnDisk=0,sizeInMemory=1979]
; M/ D9 b# t ^, S3 e --------------第三次查询后---------------------------------9 d8 {8 ^# O, J! {8 u; b9 ~
SecondLevelCacheStatistics[hitCount=2,missCount=1,putCount=1,elementCountInMemory=1,elementC% P" P! {! _" X6 A; Z. k x
ountOnDisk=0,sizeInMemory=1979] 复制代码
6 z( s: `& E( s( _7 {3 H
科帮网 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关2、本站所有主题由该帖子作者发表,该帖子作者与科帮网 享有帖子相关版权3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网 的同意4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意7、科帮网 管理员和版主有权不事先通知发贴者而删除本文
JAVA爱好者①群:
JAVA爱好者②群:
JAVA爱好者③ :