该用户从未签到
|
需要启动二级缓存,二级缓存的scope是sessionFactory。也就是说二级缓存的数据可以在由相同SessionFactory创建的多个Session中重用。3 ?& {, C5 O- U; M+ v
6 f2 r/ n* ?/ [$ X. g5 X
首先,要在hibernate.cfg.xml中设置一个cache Provider,hibernate支持多个cache实现,有EHCache,OSCache等。在非分布式环境中可以选择默认的EHCache。添加ehcahe jar$ [& g& O F- s9 ]4 H/ u. t
- <dependency>4 g h" @" q4 i# S* S& Q
- <groupId>org.hibernate</groupId>
2 f$ k6 w9 B9 } - <artifactId>hibernate-ehcache</artifactId>
' k- L% n. @2 M. X: @ - <version>4.3.5.Final</version>. ~3 V& ^' ?+ J3 R
- </dependency>
复制代码- <hibernate-configuration>6 N# |$ q0 e2 h: G! g
- <session-factory>; n6 ]- R4 J* w7 x8 m( o
- <property name="connection.driver_class">com.mysql.jdbc.Driver</property>( B: \8 F o" c) n( m7 x
- <property name="connection.url">jdbc:mysql://localhost/test</property>
3 w- f3 G" C- ~3 Q/ b5 h - <property name="connection.username">root</property>
* M9 Q5 G* n' {7 Q# O& F* y - <property name="connection.password"></property>
" c( t: q1 J& ~6 a# f( S2 q - <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
7 ^- F( h; C7 o: V2 ^% G8 } - <property name="hibernate.show_sql">true</property>7 f" l% D. W5 W/ R1 U. q% T
- <property name="hibernate.hbm2ddl.auto">update</property>0 v; e1 a5 b, V& P6 c2 J+ y) [* w
- <property name="hibernate.generate_statistics">true</property>
6 S5 k$ ~- b: n1 S" h - <property name="hibernate.cache.region.factory_class">
8 t- w& u8 L. H# S U$ @ - org.hibernate.cache.ehcache.EhCacheRegionFactory
" S' H3 z) i6 W6 ~# C' _ - </property>
0 A; N5 o+ X: R! ?$ E, _ - <mapping class="com.xinglongjian.entity.hbm.Book2"/>
2 u' ]/ E) \3 z# c0 G/ f7 s4 Z - </hibernate-configuration>
复制代码 W! G( z' s s% B0 z
第二,通过ehcache.xml配置EHCache,该文件放置于classpath的根目录下。可以在该配置文件中设置将不同的对象存储在不同的regions。- <ehcache>
) O$ W5 ]( w& b+ }, V7 H - <diskStore path="c:/data/ehcache"/>
% ?) X3 U, w6 y - <defaultCache9 ?. t' T6 H2 W$ L$ J
- maxElementsInMemory="10"' L- Y3 ?- f0 @$ |
- eternal="false"
( i; ?9 a; B- w$ V: T, V1 x - overflowToDisk="true"
' P0 ^; ?% u: {2 ?2 u, S - timeToIdleSeconds="120". V# |2 I2 R' x! j, Q/ \! b) q
- timeToLiveSeconds="120"
( u8 X: D# i: Z* T9 N - diskPersistent="false"; c% c; C+ j# A$ G8 O. F8 J- P: X
- diskExpiryThreadIntervalSeconds="120"/>
: c7 Y' u4 h) i: _: ?# t, a - <cache name="com.xinglongjian.entity.hbm.Book" maxElementsInMemory="10" eternal="false"
4 _0 S! y3 M0 ~/ T( Z5 S - overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskPersistent="false"/>" k, E* c/ J) t7 C& G
- </ehcache>
复制代码 第三,设置持久化类- @Entity3 j. d' s4 x/ B- ~! E# t6 M
- @Cacheable9 |; F) H" ]" E- B3 h/ l
- @Cache(usage=CacheConcurrencyStrategy.READ_ONLY,region="com.xinglongjian.entity.hbm.Book")' D! f1 g: X2 f0 R& ~/ u" V
- public class Book2 {
) d8 i8 N" ~. n" Q8 k - @Id
* _8 {2 N* E; V) k: e# A - @GeneratedValue
2 z3 b* `3 ]* Z$ [ - private int id;4 K" }- T/ z' P. p
- private String title;
1 ^4 S% _) [* ` - public String getTitle() {
* c3 k {/ l+ f& K: O8 t& Z# p - return title;5 Q' w" v9 S" \+ v: s% A
- }+ X* E/ n7 N Z% E% F7 V2 k- T5 E
- public void setTitle(String title) {
3 o, d; s7 B! w" G5 @! K x - this.title = title;
$ @4 D1 i9 r3 o - }
3 D! n# t1 G6 ]* H! i0 e9 R2 L Z - public int getId() {: N$ Z5 v& d- P: C# `( B
- return id;2 v" M/ l* m" ~4 J* [& |
- }* b4 |1 A5 n: N/ t5 M9 a
- public void setId(int id) {
) N# m5 z! t" a! g - this.id = id;
/ a" V1 o1 Z* C( Y( u* H1 q - }
: y: _( d" |# X5 ~5 Z0 k, ]& U - @Override' T7 N9 `, A! ^" ^$ R% F
- public int hashCode() {
* m3 {1 W+ [: q, c+ m9 G) g - final int prime = 31;- o3 I+ _2 W( g! z
- int result = 1;, x" s* M3 e- `1 {
- result = prime * result + id;
$ v# L7 E8 y; l8 c - result = prime * result + ((title == null) ? 0 : title.hashCode());1 ~' n: S" ^, ], @7 ?/ l# Y
- return result;# j8 o0 j1 D/ N# w; I
- }
' Q, |; ?" r2 ]) { - @Override5 J, c1 z0 \# X4 s; R) P
- public boolean equals(Object obj) {8 D3 \8 \8 N3 a3 ]: ^- F
- if (this == obj)) m: [# C0 [! d9 A$ V! ]
- return true;
, _. Y8 X I. E2 L. ` - if (obj == null)
) V/ B! ]- z0 V$ x. j x - return false;
0 L% ?+ E2 u0 P8 w - if (getClass() != obj.getClass())4 H' r* v, }$ W8 |" V
- return false;
" T+ t: N8 j* S, U5 v5 t' W& @ - Book2 other = (Book2) obj;
: O- S! s5 m- d% o - if (id != other.id) x: X4 `% U; l k( Y$ Z6 F
- return false;; c" s+ b" ~( D5 j5 b
- if (title == null) {4 R: |/ R# G* V, c# q
- if (other.title != null)
5 i2 D& i' e$ a2 M3 ^1 B# M8 B; q - return false;& N6 M9 b" ]' T8 o1 q
- } else if (!title.equals(other.title))- y/ i5 z, c( C
- return false;. @5 L. t# }4 T" ]. s
- return true;
4 t S' x0 e& Z4 _4 @ - }
: T7 a J! [1 D; _0 _3 ` - % ~5 Q# {7 P1 h: s
- }
复制代码 二级缓存的持久化类必须实现equals方法。' m; R: x) ]; L- G
% Q! A% h9 J' `/ X1 ?9 t
只有在SELECT时才会缓存。
% ?( s+ T9 U4 u6 c0 W, U1 P
$ a& v5 K' j+ t! n3 }在同一个session里,查询2个不同的对象,会缓存2次,- Session sess=sf.openSession();( e4 w+ b, c( Q- F, A3 `" j
- Book2 b=(Book2) sess.get(Book2.class, 17);9 k2 U6 v& M: g% Y% B6 W0 s! k
- System.out.println(b);
7 b! h+ R1 w5 T - assertEquals("spring Recipes", b.getTitle());
" t. R0 C3 l: E, u2 V$ O1 S; i - Book2 b3=(Book2) sess.get(Book2.class, 18);
6 m( L; l! A3 Q7 b - assertEquals("dfad", b3.getTitle());& _4 Z5 q% y5 `( p# k( j) }6 T5 X
- sess.close();
4 W: M; s# b7 p - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
0 [+ r" |8 _. @ - System.out.println(slcs);
复制代码 结果- SecondLevelCacheStatistics[hitCount=0,missCount=2,putCount=2,elementCountInMemory=2,elementC
( \9 \. I8 j7 h+ L3 \) D" C( ?' _ - ountOnDisk=0,sizeInMemory=3948]
复制代码
) ~) n3 M# u& F# a* ~% W; z* m 在同一个session里,查询相同的对象,会先查询一级缓存,一级缓存中有就不会查询二级缓存。- Session sess1=sf.openSession();: a; e, F- C( y4 I
- Book2 b1=(Book2) sess1.get(Book2.class, 17);
& e+ b# L. v3 U6 y% h4 S - System.out.println(b);
" \- I5 v9 L& B" s1 W - Book2 b2=(Book2) sess1.get(Book2.class, 17); e, j: z. n6 q" _- b8 A
- assertEquals("Spring Recipes", b1.getTitle());1 g9 o, D; Q, B( O& Z7 [# J
- assertEquals("Spring Recipes", b2.getTitle());
}2 X# o9 b6 h - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
. G( f2 Z1 S- Q$ q - System.out.println(slcs);
复制代码 结果,在新的session中,一级缓存不可用,就会使用二级缓存。- SecondLevelCacheStatistics[hitCount=1,missCount=2,putCount=2,elementCountInMemory=2,elementC" {/ _& N+ N! [2 |+ W
- ountOnDisk=0,sizeInMemory=3948]
复制代码 完整测试逻辑- @Test* w% y, E1 Q O! b8 h
- public void test2LCache()
( ~$ ?8 T, E9 P& K. ?8 p# p - {
+ j4 ^5 G; H W) Z. d5 U. j - Statistics stat=sf.getStatistics();//获取stat对象9 I$ h7 ~: }. n% S' s! s( Y
- Session sess=sf.openSession();6 ^) @( g8 V6 W: _- K
- Transaction tx=sess.beginTransaction();1 M/ D* G2 H+ u& l- A% T
-
8 T/ H. ~% d) M" P - //存储对象,此时不会放到缓存中
! x! K+ d" L& j7 N* ]6 B# T& l0 g - System.out.println("--------------存储对象---------------------------------");5 P! ?- f! A ^. {( S
- Book2 book=new Book2();
J3 ]; W1 l1 f' f: b* i, u* d - book.setTitle("Spring Recipes");0 S5 e: n/ r" f0 Z
- sess.saveOrUpdate(book);
! z) [ _. K5 p! R l - tx.commit();7 B8 S# Y/ N/ w0 G1 ]
- sess.close(); G& j8 M7 a9 T: G1 q* |6 Y4 Z
- System.out.println(book);
) E" C3 t# j6 X+ d. m* s r. ` - SecondLevelCacheStatistics slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book"); q% g8 ?. Y% c# S
- System.out.println(slcs);
2 R, `0 m( `# K0 J8 U. g - Cache cache=sf.getCache();7 [+ j7 A- Q H9 G, d4 M
- System.out.println(cache);
4 H8 l- ]$ ]+ k - cache.evictAllRegions();//从所有region中获取数据
9 ]7 m- u) n( _* ? - Map map=slcs.getEntries();) M( m3 h* @+ j% z: @* `
- System.out.println("Cache entries:"+map.size());/ x n% j. O" R5 |8 a
- System.out.println("--------------第一次查询后---------------------------------");" v& r+ j' B! ^: F/ |1 v, Y
- sess=sf.openSession();: a2 A% N0 ], r9 P; S6 A
- tx=sess.beginTransaction();& p) w+ ?7 t6 F( x, V( @- B6 @
- Book2 b1=(Book2) sess.byId(Book2.class).load(book.getId());//第一次查询
2 [4 m* H! v5 W, O$ P - System.out.println(b1);
, ^. c3 P8 ]$ n3 R+ B - assertEquals(book, b1);; B/ X. c! s$ k. B& X' ]4 s: X
- tx.commit();
# ]* d" q" M2 O7 a# x6 T - sess.close();
9 }, Y3 k; g$ E' I8 N - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");2 }. W# L. y2 O+ l6 N" T
- System.out.println(slcs);0 f6 X: }+ w3 K4 E) n) s
- map=slcs.getEntries();
( r! h# D" I; l - System.out.println(map.size());
2 \* A0 h+ S, s+ _7 D0 S$ [" N: {4 I - System.out.println("--------------第二次查询后---------------------------------");7 I& g+ @: C* }; w) n
- sess=sf.openSession();
+ v$ D7 e* W% e - tx=sess.beginTransaction();
! n6 h4 M2 Z( z- D( F7 j - Book2 b2=(Book2) sess.byId(Book2.class).load(book.getId());//第二次查询
" a) n6 K! Z$ x2 h0 ^ - System.out.println(b2);
* E6 d( L* ^: G% | - assertEquals(book, b2);
# ~+ M$ l: v# f2 u- G - tx.commit();
1 U* G6 M( e8 f7 V* X) [ - sess.close();( ~6 r2 g; L2 j" J: t; B5 r4 W
-
+ X& I7 S6 [0 x/ P3 m - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");* t- b' c' G* v: z+ ]
- System.out.println(slcs);
% \- x. ]- I4 R5 G. g: n v1 ]$ h - // this is the initial select+ d6 ]/ k) g5 X
- assertEquals(stat.getSecondLevelCacheMissCount(), 1);
[9 t' l6 g- J( O5 {$ ] - // we put one element in the cache from the miss
6 N5 }3 o7 `- ?% @+ R - assertEquals(stat.getSecondLevelCachePutCount(), 1);
: ?+ L. ~/ \' S4 E3 k5 {& L. _, ?: n - // we still didn't hit the cache, because of 1L cache# B$ V+ x2 w5 ], ?/ |$ |
- assertEquals(stat.getSecondLevelCacheHitCount(), 1);
+ e; p3 ~# E0 Q6 d6 H - System.out.println("--------------第三次查询后---------------------------------");
% [% k. T7 f D - sess=sf.openSession();
% i: V' \. F+ ?; O i! T) j [# u - tx=sess.beginTransaction();
1 U1 A/ \: _* f" l1 ] - b1=(Book2) sess.byId(Book2.class).load(book.getId());//第三次查询1 m- G( b( i8 w0 R: n$ ]# w
- assertEquals(book, b1); Q/ k/ d, [, E: j0 u/ T. e3 \8 ^
- tx.commit();
$ a; \# z9 L: G - sess.close();
' t0 Z# n! h/ G( ?1 o$ p8 y( h# W - 8 O$ A; X3 M, d$ T4 T% }
- slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
3 k6 F. I8 l, ]# C/ E, {) S - System.out.println(slcs);
* |! T+ g7 I0 r, P9 V5 O* Y! H - // same miss count (we should hit now). C- ^& o, O. K
- assertEquals(stat.getSecondLevelCacheMissCount(), 1);) s3 [" [8 M U- C/ t
- // same put count (we didn't put anything new)! h% p$ T! o+ P. C
- assertEquals(stat.getSecondLevelCachePutCount(), 1);7 H) D* F; H6 ^% [
- // now we hit the 2L cache for load5 I! b$ g, R* \; K$ |% |
- assertEquals(stat.getSecondLevelCacheHitCount(), 2);
% X0 z0 e4 C1 A- J/ |" L -
9 |& S$ u3 B; j6 |( _- ?0 i9 d - }
复制代码 完整测试结果- Hibernate: delete from book2
4 j% }; n4 t' C9 R9 G0 z - --------------存储对象---------------------------------' C' ?- k2 P- h8 T( b! `
- Hibernate: insert into Book2 (title) values (?)1 k7 c; r! N* N8 \, z% k8 Q/ X
- com.xinglongjian.entity.hbm.Book2@521e083b
9 x: H4 O2 Y D9 B9 y - SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=0,elementCountInMemory=0,elementCountOnDisk=0,sizeInMemory=0]' c: Q' L* P! x/ r% C
- org.hibernate.internal.CacheImpl@4830f6
& Z2 C. f* H/ w - Cache entries:07 H' D% y; [) l* m! [7 o' Z
- --------------第一次查询后---------------------------------4 `) K# _; }$ u. I" s
- Hibernate: select book2x0_.id as id1_0_0_, book2x0_.title as title2_0_0_ from Book2 book2x0_
4 e$ F6 C3 Z0 V - where book2x0_.id=?
* | }/ k5 V! M& S: b0 I - com.xinglongjian.entity.hbm.Book2@521e083b
$ ^1 n9 ^8 H. ]3 Z( [ - SecondLevelCacheStatistics[hitCount=0,missCount=1,putCount=1,elementCountInMemory=1,elementC
% W! T. l( o& _ - ountOnDisk=0,sizeInMemory=1979]' _8 v+ j' D$ K# J' a
- 1& `/ E, e" @6 K' }
- --------------第二次查询后---------------------------------
: s) e% Z1 U9 p- i - com.xinglongjian.entity.hbm.Book2@521e083b
1 Z2 n8 y: f) s) q ~# I0 G) j - SecondLevelCacheStatistics[hitCount=1,missCount=1,putCount=1,elementCountInMemory=1,elementC2 Q% F5 }% s# w8 T
- ountOnDisk=0,sizeInMemory=1979]
z) m9 g9 E4 g9 { K; Z - --------------第三次查询后---------------------------------9 l& H! D: T% z: w
- SecondLevelCacheStatistics[hitCount=2,missCount=1,putCount=1,elementCountInMemory=1,elementC0 b- S0 \1 y* E+ B
- ountOnDisk=0,sizeInMemory=1979]
复制代码 , v4 V. q/ }' u
|
|