该用户从未签到
|
需要启动二级缓存,二级缓存的scope是sessionFactory。也就是说二级缓存的数据可以在由相同SessionFactory创建的多个Session中重用。# J; R, L2 r. ?1 W% a
M$ V/ |# }, t' c( N首先,要在hibernate.cfg.xml中设置一个cache Provider,hibernate支持多个cache实现,有EHCache,OSCache等。在非分布式环境中可以选择默认的EHCache。添加ehcahe jar) r, {9 j" I( f) Q0 S
- <dependency>$ J/ j; o& e/ V! b$ @: e
- <groupId>org.hibernate</groupId>
+ w( b% h' E: M5 |! ?: b - <artifactId>hibernate-ehcache</artifactId>
0 D2 P3 e$ u; l6 U& K - <version>4.3.5.Final</version>
% w' w' q. j0 j: e7 S3 e2 p - </dependency>
复制代码- <hibernate-configuration>
7 j' H0 L( P! _2 @ R - <session-factory>
! A7 Q# k2 x, ?7 r1 w' i - <property name="connection.driver_class">com.mysql.jdbc.Driver</property>3 y5 M2 b+ w$ \' u
- <property name="connection.url">jdbc:mysql://localhost/test</property>
3 M1 z0 g, r7 e& G( O - <property name="connection.username">root</property>+ E0 v2 P9 m4 T6 y% \9 w
- <property name="connection.password"></property>
9 z1 h5 j7 l* i A - <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
* @2 H% K- T. L8 N! } - <property name="hibernate.show_sql">true</property>
$ }& m \) Y! ]& `6 x. y0 C( ?) T - <property name="hibernate.hbm2ddl.auto">update</property>! H; c$ E) }/ Z( A' v
- <property name="hibernate.generate_statistics">true</property> s4 u0 {$ H6 r% {/ {! G
- <property name="hibernate.cache.region.factory_class">) ?1 N J" }. A
- org.hibernate.cache.ehcache.EhCacheRegionFactory
6 ?, A7 H) A# ?! e - </property>
6 p8 E5 P6 A4 A7 q* r - <mapping class="com.xinglongjian.entity.hbm.Book2"/>! p3 n, u- M R5 v; I- Y9 ]$ X& C
- </hibernate-configuration>
复制代码 ' z( H- N. w; Q& F' F# b1 v
第二,通过ehcache.xml配置EHCache,该文件放置于classpath的根目录下。可以在该配置文件中设置将不同的对象存储在不同的regions。- <ehcache>
7 w4 H% {( {6 [, l' j* P - <diskStore path="c:/data/ehcache"/>
) y' U" U9 r6 o5 m - <defaultCache& x9 C- [9 Z% a( v5 x$ I
- maxElementsInMemory="10"
7 c3 \. H S' w$ q - eternal="false"/ z; N# b+ X6 g2 ~
- overflowToDisk="true"/ n3 e, m) O* g& I7 X: O- K
- timeToIdleSeconds="120"
3 [( T" ]7 q6 P( o: V - timeToLiveSeconds="120"% U6 s2 i, g) o( Z
- diskPersistent="false"7 @; v" B' J+ b7 a2 A( L# z
- diskExpiryThreadIntervalSeconds="120"/>7 R' ~- V& V0 E; m
- <cache name="com.xinglongjian.entity.hbm.Book" maxElementsInMemory="10" eternal="false" ) k. v/ S) b3 I1 D. r, E9 |
- overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskPersistent="false"/>; y( e5 F% X' J; X; H5 x
- </ehcache>
复制代码 第三,设置持久化类- @Entity7 ~" r! s6 |% p. k- q( Y5 E
- @Cacheable8 N+ V: E( e1 J. J: j
- @Cache(usage=CacheConcurrencyStrategy.READ_ONLY,region="com.xinglongjian.entity.hbm.Book")
2 m( \6 M; m6 y d# E( y9 \ - public class Book2 {
}2 u1 o$ N0 n. F( X - @Id
: u( y) D! G- F. I0 m; g# f - @GeneratedValue
" l3 p# S' i6 _9 `6 _# U6 c& y3 R - private int id;4 X) H H3 n+ e8 c7 Z. i9 `
- private String title;
' V u7 C. g( Y" {# b7 S - public String getTitle() {
) G& L. w3 U4 z, J - return title;
4 s( z$ \: [6 G) {. ]$ S+ s& W8 d - }
5 x" e' X& n# H4 F - public void setTitle(String title) {
, C0 d2 C' Q4 Z* e9 i/ `; U - this.title = title;
+ [3 M/ Z( c6 C - }; D' T6 N* h* R
- public int getId() {
) m) e# p _, y& t' c# R* { - return id;
+ q0 u) Z4 ^" _1 ]5 v- \+ k - }
5 t) E; x4 D9 a+ ` - public void setId(int id) {
- |" z+ U9 l$ a- R$ k& }$ ^ - this.id = id;# r* s* H1 }9 S
- }
* c% c1 ]2 l& C, ~ - @Override2 }# K2 r0 N8 f7 f
- public int hashCode() {
: ~* B: P% i- m+ A - final int prime = 31;4 t4 o/ `& X, Y0 x; K
- int result = 1;, d6 g8 R, v1 F2 J
- result = prime * result + id;
m6 P) v: O7 C# w - result = prime * result + ((title == null) ? 0 : title.hashCode());& h r4 \& _- D4 y- T8 G i- C. A8 L% {4 q
- return result;
" U' N! k+ l9 n. a( p - }
" ?- [- E4 v, |* ]5 K - @Override
6 ^/ b/ o0 v7 D) D4 T- L) B% F - public boolean equals(Object obj) {
& A- d+ _+ i& Q) V# C - if (this == obj)
9 b) {+ }" f1 H! m6 x8 P* M - return true;
3 E7 s; W$ B' i - if (obj == null)
7 x4 F7 F& R7 \1 n. j8 f# O6 m - return false;
, d; u( L/ E8 `. a/ P - if (getClass() != obj.getClass())
9 X% x' L2 K! g* x: L" ]2 G - return false;
: _ k1 v. h) i - Book2 other = (Book2) obj;4 B6 }* H, W( I+ H/ T7 _
- if (id != other.id)+ s1 G* S/ K) U0 s' p: N( o
- return false;" N- |4 n) k3 C* Q: ]4 z
- if (title == null) {
( I: `/ J$ v5 g( J - if (other.title != null)
5 w& D( x5 K% ^6 T1 V2 ~ - return false;- m p# [, T7 V( W- E1 V- L6 i
- } else if (!title.equals(other.title))( f' N; b" W* a4 Z1 j7 x
- return false;: g# e p$ w7 H8 L$ {) f; w
- return true;
2 {1 z2 H5 p8 A- K# V3 U - }
2 }) r3 r# `+ r0 d+ } -
+ ?% j! \- k; ^. g0 [ - }
复制代码 二级缓存的持久化类必须实现equals方法。; F6 c; n9 V! ~. |
, s, Z# R0 n( w ]6 n
只有在SELECT时才会缓存。8 W Z, ?7 o6 N4 Z
0 f% L: O( f6 `& ]( [
在同一个session里,查询2个不同的对象,会缓存2次,- Session sess=sf.openSession();
' V# D; x; \# L2 P; q - Book2 b=(Book2) sess.get(Book2.class, 17);
* B2 E) \+ H/ @0 F& q1 P - System.out.println(b);0 M3 i- t! s" r" j( [: L' G
- assertEquals("spring Recipes", b.getTitle());4 g0 X+ N, q$ U
- Book2 b3=(Book2) sess.get(Book2.class, 18);
8 R' n! W0 Q) V - assertEquals("dfad", b3.getTitle());7 i2 O6 n G- ^- g( R$ r7 \0 @
- sess.close();* g5 Y* x0 b/ K0 f
- slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");0 L. t& `5 F, [( g+ e& u, Z
- System.out.println(slcs);
复制代码 结果- SecondLevelCacheStatistics[hitCount=0,missCount=2,putCount=2,elementCountInMemory=2,elementC
5 l; o( O1 W# N) i" [6 R - ountOnDisk=0,sizeInMemory=3948]
复制代码 9 m# C0 V. ^1 q. y8 p) M
在同一个session里,查询相同的对象,会先查询一级缓存,一级缓存中有就不会查询二级缓存。- Session sess1=sf.openSession();
$ z" b0 t+ V0 O) E% W* D/ `3 ^6 D - Book2 b1=(Book2) sess1.get(Book2.class, 17);: E g9 \! i& e
- System.out.println(b);8 g! s* ` s# B; k6 W
- Book2 b2=(Book2) sess1.get(Book2.class, 17);, a- U7 E( y$ x1 v# @
- assertEquals("Spring Recipes", b1.getTitle());3 h: O) s6 i& D8 Y1 W' @5 k
- assertEquals("Spring Recipes", b2.getTitle());
2 k: Z' L0 }2 v N" W" N2 M$ [ - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
' B1 ?7 [; r8 a/ l - System.out.println(slcs);
复制代码 结果,在新的session中,一级缓存不可用,就会使用二级缓存。- SecondLevelCacheStatistics[hitCount=1,missCount=2,putCount=2,elementCountInMemory=2,elementC
! K6 l+ u/ H; `1 j - ountOnDisk=0,sizeInMemory=3948]
复制代码 完整测试逻辑- @Test2 [; ]$ I1 H( I
- public void test2LCache()
p$ h$ K+ h; |, I - {" O: Y* t/ ^8 Y; } \
- Statistics stat=sf.getStatistics();//获取stat对象! Y, h, j& ]1 `6 _/ r$ c
- Session sess=sf.openSession();
4 X V% e( \: T" } - Transaction tx=sess.beginTransaction(); A8 ^; m, W2 B- ~% c& A: `( D
- * T# J" u6 A" d
- //存储对象,此时不会放到缓存中
" o7 t7 {9 g& k p: i6 Z - System.out.println("--------------存储对象---------------------------------");" _" u" V" f1 L& a+ M2 W6 Q# r
- Book2 book=new Book2();
' ~( t# I: j3 `* g) X# f8 @9 F - book.setTitle("Spring Recipes");" E" U6 o% `! x
- sess.saveOrUpdate(book);
, u& c, l* c+ C3 @/ P+ ]" V. Y - tx.commit();& B0 [/ W$ N \3 z, X9 i0 G0 u0 H
- sess.close();) \0 ~* _1 N- O" m) H" b
- System.out.println(book);! C. _; [0 v5 u. a/ b5 O+ q. Z1 D9 R
- SecondLevelCacheStatistics slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");! k4 t& h5 U: f5 |1 j
- System.out.println(slcs);
& A1 d; h# Z# C# A4 {& R5 U& d - Cache cache=sf.getCache();6 y7 \" u$ _- E# P# }+ G! {) z
- System.out.println(cache);
! d; H7 W9 Y: P5 k - cache.evictAllRegions();//从所有region中获取数据
" E: d' {7 j; ~8 i - Map map=slcs.getEntries();4 g9 f- x, v# K. T3 X
- System.out.println("Cache entries:"+map.size());0 J1 m2 b! \. ^% k$ \
- System.out.println("--------------第一次查询后---------------------------------");2 y* o% {5 W r6 r0 @% j
- sess=sf.openSession();2 ]3 s& ^1 l8 N
- tx=sess.beginTransaction();
# S! H# F& r2 [! k7 S6 v" ^4 F( Y - Book2 b1=(Book2) sess.byId(Book2.class).load(book.getId());//第一次查询
# ~. ]" R& k [7 e7 S `$ B - System.out.println(b1);
% k! W2 E/ t; r ^5 L - assertEquals(book, b1);& J, K& D' A6 X R
- tx.commit();
* t# C* s. W( o - sess.close();+ }7 [4 D! ^; ^, D
- slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
7 M" e+ C, G; u( u& r - System.out.println(slcs);. r; X) [1 L! @0 b0 [9 S
- map=slcs.getEntries();
/ [3 g' H$ Y8 B2 F! l8 x - System.out.println(map.size());
3 V Q* V. j1 u1 g @ - System.out.println("--------------第二次查询后---------------------------------");
Q, H5 A1 \2 k( s ` - sess=sf.openSession();
* C1 A0 p( K) k9 q% r3 Q/ w9 X - tx=sess.beginTransaction();
( f6 v! b$ \1 ~9 g9 R1 _: K - Book2 b2=(Book2) sess.byId(Book2.class).load(book.getId());//第二次查询
- { P5 e' E& h. ~ - System.out.println(b2);
* o, w0 U' S6 @9 P' B) j - assertEquals(book, b2);
' J* S) ]2 u+ a$ q - tx.commit();) j& [" t3 @0 m& `9 {% q
- sess.close();
8 k0 t+ R: G z* S' V0 |% A -
: |% I m" T9 ~. @ - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
4 L* c3 L/ t- D1 Q, }! T% T# Q - System.out.println(slcs);
: M) o, y# W6 t - // this is the initial select
+ B" _$ a9 m# G% I; I, x - assertEquals(stat.getSecondLevelCacheMissCount(), 1);6 Q' [; i; ]3 l' X
- // we put one element in the cache from the miss5 M' A* r/ ~: D
- assertEquals(stat.getSecondLevelCachePutCount(), 1);
) Q( i) N1 d U0 O' C# j - // we still didn't hit the cache, because of 1L cache
( J) L3 L! M1 e5 R7 [ - assertEquals(stat.getSecondLevelCacheHitCount(), 1);
- y5 i1 u8 G. U# d7 t+ ^9 u - System.out.println("--------------第三次查询后---------------------------------");$ w2 `% t- ~, ~9 W M% C2 b/ |
- sess=sf.openSession();
/ C' h* Y, W. T: S - tx=sess.beginTransaction();
5 z5 C/ H) `' O% }$ \9 }! n+ f% V - b1=(Book2) sess.byId(Book2.class).load(book.getId());//第三次查询
% }( [9 E( v" H - assertEquals(book, b1);
* B9 b/ [0 d) K9 ?6 Q7 S! M1 S - tx.commit();: {, H( O( S( y* a& P% O* }' U* W
- sess.close();
, e( R3 D; F, @ - 1 d. Q8 v, \8 m# A9 r
- slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
* n. Y1 L( Q" K& t% f9 c/ d1 s - System.out.println(slcs);
# i; B. H. G: A" [) o( `' u - // same miss count (we should hit now)
9 ~& g4 T# \9 Z" }3 O - assertEquals(stat.getSecondLevelCacheMissCount(), 1);
$ O m# e7 q& S9 T, K: e - // same put count (we didn't put anything new)! s/ d- g* l' ]8 ?6 V
- assertEquals(stat.getSecondLevelCachePutCount(), 1);
: M% s6 e) H0 z- p2 J - // now we hit the 2L cache for load! j/ X& \+ b4 E4 h2 Y
- assertEquals(stat.getSecondLevelCacheHitCount(), 2);& T( p, C7 p: L% u& _
- 0 y$ z) a* A c+ }# t7 I0 X9 y& n
- }
复制代码 完整测试结果- Hibernate: delete from book2: Z s. ~* y6 @! V ~3 c3 x3 W
- --------------存储对象---------------------------------
X, Q: \/ L7 O- y$ I6 T9 A - Hibernate: insert into Book2 (title) values (?)- r0 C4 t1 J4 Z+ g$ j( e
- com.xinglongjian.entity.hbm.Book2@521e083b8 _) Y. ~9 o- V- S4 ?2 L5 x* I$ |! S& x
- SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=0,elementCountInMemory=0,elementCountOnDisk=0,sizeInMemory=0]
% c" _% G8 d/ i; m/ `0 q. r0 G4 |6 [ - org.hibernate.internal.CacheImpl@4830f6
$ E! F7 ?! g' v# X - Cache entries:0
! p- y% F4 e/ w! Q4 W1 a - --------------第一次查询后--------------------------------- p6 A2 L4 n8 V/ K5 l! C
- Hibernate: select book2x0_.id as id1_0_0_, book2x0_.title as title2_0_0_ from Book2 book2x0_2 a! o9 j) C% w: h
- where book2x0_.id=?
% G6 q) x/ f+ { - com.xinglongjian.entity.hbm.Book2@521e083b
1 N) H$ j! M. I% L$ e* l - SecondLevelCacheStatistics[hitCount=0,missCount=1,putCount=1,elementCountInMemory=1,elementC" ^5 p# {. b( u" o) M2 Q) c
- ountOnDisk=0,sizeInMemory=1979]
# ]. d) \9 Z, g( a# { - 1
, x1 v9 O" S$ _' a& O - --------------第二次查询后---------------------------------7 |7 O2 D' T, ^+ `- Y
- com.xinglongjian.entity.hbm.Book2@521e083b# P, T) O: r$ Z. [! o5 d& U
- SecondLevelCacheStatistics[hitCount=1,missCount=1,putCount=1,elementCountInMemory=1,elementC3 B( B- h( l6 l
- ountOnDisk=0,sizeInMemory=1979]
$ U7 a8 D, Z- H7 h7 }, p, F - --------------第三次查询后---------------------------------
) l0 C4 P; `* k9 u! q - SecondLevelCacheStatistics[hitCount=2,missCount=1,putCount=1,elementCountInMemory=1,elementC- X$ L- W9 c+ C/ Y0 ]4 v/ r
- ountOnDisk=0,sizeInMemory=1979]
复制代码 7 z. @7 X+ j1 i; F6 |' i
|
|