该用户从未签到
|
需要启动二级缓存,二级缓存的scope是sessionFactory。也就是说二级缓存的数据可以在由相同SessionFactory创建的多个Session中重用。9 B1 e a: n- Q" W$ {( Q
" \( ?, h5 i9 p
首先,要在hibernate.cfg.xml中设置一个cache Provider,hibernate支持多个cache实现,有EHCache,OSCache等。在非分布式环境中可以选择默认的EHCache。添加ehcahe jar+ A/ y4 S. D6 @
- <dependency>. z5 @ H/ z" m" \
- <groupId>org.hibernate</groupId>
6 d9 @5 g; c+ |; }$ m& | - <artifactId>hibernate-ehcache</artifactId>; k3 U* x+ e' |; \; s
- <version>4.3.5.Final</version>
' i8 U7 ~" m/ @! Z* D - </dependency>
复制代码- <hibernate-configuration>
: s+ F, P" K# F - <session-factory>
& P( }& f3 ^3 E1 T - <property name="connection.driver_class">com.mysql.jdbc.Driver</property>$ G$ r. s, T4 D1 B9 O+ r/ o* L: B
- <property name="connection.url">jdbc:mysql://localhost/test</property>
' i- B% P) z; E! ^9 V; |) X - <property name="connection.username">root</property>
$ N8 x/ m9 f) O/ w: Q* a: E. R - <property name="connection.password"></property>
) T) H8 ^" v2 Y# k7 G - <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
# `7 p! v; K+ S - <property name="hibernate.show_sql">true</property>
- k% H3 |7 I* v3 R - <property name="hibernate.hbm2ddl.auto">update</property># ?8 B+ ^3 M) Q( S, J2 E( H7 f! o
- <property name="hibernate.generate_statistics">true</property>
: v+ s& @( u& y" o# p - <property name="hibernate.cache.region.factory_class">3 I* |1 n$ }+ t" \ D( J- l
- org.hibernate.cache.ehcache.EhCacheRegionFactory0 D2 d& o: T P: K0 f/ J) k1 C
- </property>
" n4 `5 \; c9 } - <mapping class="com.xinglongjian.entity.hbm.Book2"/>0 D+ t! \$ R4 f1 X2 e# Z
- </hibernate-configuration>
复制代码
/ j- P2 |' O/ L: U+ L8 v- g 第二,通过ehcache.xml配置EHCache,该文件放置于classpath的根目录下。可以在该配置文件中设置将不同的对象存储在不同的regions。- <ehcache>; f( m; C; a& I" z
- <diskStore path="c:/data/ehcache"/>1 g2 o, ?1 s+ [# |6 {
- <defaultCache0 o! f2 s/ ] y9 s
- maxElementsInMemory="10"
: x( X: Z' f5 O. Q5 S4 _$ H - eternal="false"
8 A* i. s O( U$ \1 Y) M - overflowToDisk="true"( t: a C' ^" R2 ?% P
- timeToIdleSeconds="120"9 v) b7 Q, M9 l$ A, {
- timeToLiveSeconds="120"( Z: U% j9 u @. g6 o9 z
- diskPersistent="false"
, `/ \: }/ c+ c" w% p - diskExpiryThreadIntervalSeconds="120"/>, D9 L+ Z1 C/ W" y
- <cache name="com.xinglongjian.entity.hbm.Book" maxElementsInMemory="10" eternal="false" P7 O& y" E7 _' L W' H7 z9 H7 \
- overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskPersistent="false"/>
, [& ?0 s& M; `/ P9 j x - </ehcache>
复制代码 第三,设置持久化类- @Entity# y; J9 ]- ~! `5 z
- @Cacheable" }# n$ h, `# S6 n* V
- @Cache(usage=CacheConcurrencyStrategy.READ_ONLY,region="com.xinglongjian.entity.hbm.Book")
- L- U; Y9 r! i; b$ X1 }! K* w: G+ x - public class Book2 {
: e q# P! k$ H. n& l0 O - @Id
; M, U0 q0 x9 m6 h& C! ` - @GeneratedValue
# D1 H% G e# a w/ Y9 t l - private int id;7 `9 u9 j0 h& a. u0 v
- private String title;
$ p7 }4 O2 ~9 [8 H& k9 n% t - public String getTitle() {
" g# |/ T- ]8 M6 G) K - return title;
$ n1 E5 w/ P8 y - }
5 S2 I* Y' Z, v+ @. V) I2 v4 L - public void setTitle(String title) {5 |! H7 a( _" y# ]+ z4 b% ]: U
- this.title = title;
% c: F$ H2 A3 g& G% ]# Z; r- [& Q - }, t/ k0 Z6 `+ ^8 n
- public int getId() {3 c1 Y; o u" Q' D1 }+ U5 L
- return id;- {* {5 s0 D% Z4 t
- }5 L- B z" {. }2 h6 ]
- public void setId(int id) {* I" x z' u4 I( O z
- this.id = id;" a* d7 h- y$ [: ^- ?& f, g4 k
- }
/ t0 d2 b$ d" d% v$ T: o; e - @Override0 ?5 h! D( F0 ^1 q
- public int hashCode() {7 r2 d9 @1 n+ E7 }. |
- final int prime = 31;
5 v& ^$ [' U1 c$ W+ _2 N, _ - int result = 1;
% n' I3 {' P7 s, }3 A - result = prime * result + id;. w" X7 v! {" A! c
- result = prime * result + ((title == null) ? 0 : title.hashCode());
, N+ v+ f8 j2 Z+ p0 w1 L# F - return result;
# |2 x) W$ {4 t - }* w: V3 k J) r) ?' c3 d
- @Override
2 }! J$ V6 X3 m, D - public boolean equals(Object obj) {
) P6 b* l/ B. e& v, X5 n i) o - if (this == obj)
' F/ U1 \+ v$ x5 ^5 D - return true;2 b, j0 X" Q! c; y- N5 s
- if (obj == null)8 ~! Q$ N; z; i3 X: w
- return false;
) G5 d) m5 G3 G9 G% Q - if (getClass() != obj.getClass())+ _- z/ H- z* G8 S0 P! r6 J/ p
- return false;
( i7 @( Y' p. A5 C6 E6 `; I& K7 z - Book2 other = (Book2) obj;8 n' |/ W3 }4 y! |) V i
- if (id != other.id)
: `) f* T# A) m7 n3 d7 G: P. _* U - return false;
" @4 V0 j& H; z - if (title == null) {
, I, K/ A4 {! Z- Y% v% W - if (other.title != null)
C) w; Y# k; b2 |. J) _3 X - return false;! b+ C% b2 n6 T0 O% s* B
- } else if (!title.equals(other.title))' ]( d3 v8 K6 d% Z) Y9 X, `7 _" @
- return false;' `' h' x( D: \/ U) ]
- return true;
3 l, C) d5 t/ S r: B4 a) Q6 G/ _3 c - }
) ~& Z4 l$ y) a* S8 M3 q - 4 x) ]0 v& |# H
- }
复制代码 二级缓存的持久化类必须实现equals方法。
Y: Q% E" @: _/ F6 u5 W5 g: T
3 a% r, R( }* X# q5 c& A( }" q只有在SELECT时才会缓存。3 X! m2 ?6 q2 _
! ^: m U1 W: W& z, i" o在同一个session里,查询2个不同的对象,会缓存2次,- Session sess=sf.openSession();
# _) K: E+ Z, C5 L - Book2 b=(Book2) sess.get(Book2.class, 17);
% n: X! v6 I% l$ V0 S6 N - System.out.println(b);4 U h- E( r% @" }
- assertEquals("spring Recipes", b.getTitle());6 L! _6 W* {) ?+ y
- Book2 b3=(Book2) sess.get(Book2.class, 18);
: D3 S7 a/ C6 E e! ^$ d - assertEquals("dfad", b3.getTitle());
6 w; t( a1 L0 b - sess.close();) c0 U v) e( T& e" H M3 o& E
- slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");; K( P) Y! j9 W X
- System.out.println(slcs);
复制代码 结果- SecondLevelCacheStatistics[hitCount=0,missCount=2,putCount=2,elementCountInMemory=2,elementC9 N j7 F7 p9 u% L3 W9 d0 m
- ountOnDisk=0,sizeInMemory=3948]
复制代码 D5 s; H: w& u7 c) r& s0 r
在同一个session里,查询相同的对象,会先查询一级缓存,一级缓存中有就不会查询二级缓存。- Session sess1=sf.openSession();) _6 z7 N- F3 `& _5 g }+ X: v- y
- Book2 b1=(Book2) sess1.get(Book2.class, 17);* U+ I' E- c: t& s" d
- System.out.println(b);2 v- m `, k! m$ Y r
- Book2 b2=(Book2) sess1.get(Book2.class, 17);
5 I* y, }+ S0 p - assertEquals("Spring Recipes", b1.getTitle());
a q f- l) W( _* R7 o* ]$ j - assertEquals("Spring Recipes", b2.getTitle());, h. x/ z6 \2 }" h( l
- slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");8 w9 t# H' V' e/ i3 }' ^
- System.out.println(slcs);
复制代码 结果,在新的session中,一级缓存不可用,就会使用二级缓存。- SecondLevelCacheStatistics[hitCount=1,missCount=2,putCount=2,elementCountInMemory=2,elementC
' U4 @/ D5 m/ C: F# V* y - ountOnDisk=0,sizeInMemory=3948]
复制代码 完整测试逻辑- @Test
) M4 ?3 d* n/ H8 `" v3 ^ - public void test2LCache()
* Z/ I4 s5 l# E/ z( s. m4 m - {
/ v0 E) w- ]0 P - Statistics stat=sf.getStatistics();//获取stat对象
# s* C( {& F( A3 Q$ e - Session sess=sf.openSession();% t7 ] K$ n* a$ K3 w: l+ B
- Transaction tx=sess.beginTransaction();
# h5 E# M1 W) t+ }- P - ( @% c, h9 g6 \. S6 ]& s$ S
- //存储对象,此时不会放到缓存中4 d7 x7 p Y1 x+ `3 t
- System.out.println("--------------存储对象---------------------------------");2 C9 ^* n b$ i7 c( g
- Book2 book=new Book2();1 Q- F( P' D+ ~3 \" G6 E
- book.setTitle("Spring Recipes");
" q* F* I, d& S$ D" ~$ O - sess.saveOrUpdate(book);. ?, `5 O4 g6 H8 S% ~$ c3 ~. t, o
- tx.commit();
- |1 ^; j7 v0 J* X6 d3 ?2 @ - sess.close();
8 ^( c% P+ {/ j: b' y - System.out.println(book);
! Y7 F* v3 t7 e5 y - SecondLevelCacheStatistics slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");4 K' N. i: v6 M- R
- System.out.println(slcs);: O4 R( {, K& t: Q6 R; S& R
- Cache cache=sf.getCache();
. e7 O& j$ n) F, e - System.out.println(cache);. T& v) Q- k$ ~9 `
- cache.evictAllRegions();//从所有region中获取数据
3 f) |9 \, U& }! P% z4 W - Map map=slcs.getEntries();" U* q c- W. Q7 [3 q! x
- System.out.println("Cache entries:"+map.size());& p3 |. r" U5 G! f
- System.out.println("--------------第一次查询后---------------------------------");' w9 ~' j" t) C+ V- x9 z$ x7 j! |
- sess=sf.openSession();; G7 T! g, X6 K" Z: ]2 s E
- tx=sess.beginTransaction();
) F7 d/ N4 m& F: W - Book2 b1=(Book2) sess.byId(Book2.class).load(book.getId());//第一次查询+ S0 _+ t$ z& @" j: t3 w1 \% S
- System.out.println(b1);
+ R# g3 W, l# _! O) s @- {) Q0 y - assertEquals(book, b1);+ Y' v; B1 U `2 Y$ c
- tx.commit();9 O1 q; c7 h$ L: T9 w4 y( H" f' Z
- sess.close();
; o7 ?5 k1 T Z/ T6 Z* T, l - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book"); Z' B- I9 e5 n- D
- System.out.println(slcs);
( ]+ ?7 }" s8 o" t - map=slcs.getEntries();
2 a5 a+ g" p8 V S- N - System.out.println(map.size());
6 D, O& ]* Q9 g) m4 s" v F - System.out.println("--------------第二次查询后---------------------------------");7 O9 X2 u+ {9 l* n' g6 `. {5 s4 W
- sess=sf.openSession();7 }& p: V( P# T8 R M8 z- [3 I
- tx=sess.beginTransaction();
) H1 d7 {, l5 Q. v% |9 K8 \ - Book2 b2=(Book2) sess.byId(Book2.class).load(book.getId());//第二次查询
1 X2 k* j) ]" E9 H2 @& h9 N" Z - System.out.println(b2);; f) L$ v$ ^1 }
- assertEquals(book, b2);
5 S8 T* O! T& z: S; T - tx.commit();
' f( v4 R, o. K$ P - sess.close();
5 ~% L2 x! I1 |" a -
8 ^7 W f- x3 U* a, w/ c0 r - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
* ~+ D$ m! ]0 I - System.out.println(slcs);
3 H8 o* H+ u2 v8 {+ G" g# y Z - // this is the initial select
% H5 [' y6 r. i - assertEquals(stat.getSecondLevelCacheMissCount(), 1);
2 R; H& p% n7 Q% \3 N - // we put one element in the cache from the miss
% W: W0 E+ l) c" L4 E4 f - assertEquals(stat.getSecondLevelCachePutCount(), 1);8 b! `. G# P9 \+ c
- // we still didn't hit the cache, because of 1L cache
+ c) c6 M, r: J( D( v' Z0 h - assertEquals(stat.getSecondLevelCacheHitCount(), 1);
' M, s8 g; E% I2 e5 g8 J* e - System.out.println("--------------第三次查询后---------------------------------");! j% Y4 E9 f5 i! D% v! D6 R
- sess=sf.openSession();3 F% Y8 u; j( g4 k S
- tx=sess.beginTransaction();+ u3 V2 ?; _ n" m, ^: @
- b1=(Book2) sess.byId(Book2.class).load(book.getId());//第三次查询
6 |4 i0 @& r; u7 ?6 S- v1 U5 U - assertEquals(book, b1);
+ u( ]2 F9 q: v. Y9 T! {1 n$ R - tx.commit();7 b9 [" u* @6 G
- sess.close();0 Y) K5 M, u- W" T7 i" |
- $ ?; b Z' n; K8 v% d8 }
- slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");0 E+ V& Q* A) O( Q# ~; J+ o7 J
- System.out.println(slcs);
& s% s _; e4 D) [% _9 v - // same miss count (we should hit now)
8 t$ U# {9 Z! B9 X( u6 E$ O9 k - assertEquals(stat.getSecondLevelCacheMissCount(), 1);
7 k; f* z( [1 \! G; g: R* j - // same put count (we didn't put anything new)
6 E9 K" }; g8 `( E3 i - assertEquals(stat.getSecondLevelCachePutCount(), 1);
3 s5 X/ t6 v/ g1 Z - // now we hit the 2L cache for load
% x+ r; E, ~/ ` - assertEquals(stat.getSecondLevelCacheHitCount(), 2);
+ M$ z& X; Z8 x% D6 ~ - 6 T* F# `+ ~1 S; d- U. W
- }
复制代码 完整测试结果- Hibernate: delete from book2
) F& a3 h8 B- }4 n - --------------存储对象---------------------------------# d5 O* W; ^, `' |
- Hibernate: insert into Book2 (title) values (?): W5 O. O/ l6 @3 E ]
- com.xinglongjian.entity.hbm.Book2@521e083b0 _6 I" L" p9 P; W, F6 w
- SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=0,elementCountInMemory=0,elementCountOnDisk=0,sizeInMemory=0]
5 F! @7 |) r+ v+ B: Y- O' E - org.hibernate.internal.CacheImpl@4830f6; T" Q9 H" k- J$ e) _) {
- Cache entries:0
5 i- r) T) }$ O! p. D3 p9 q - --------------第一次查询后---------------------------------
: @* u, P# y4 n& R. {' q: z - Hibernate: select book2x0_.id as id1_0_0_, book2x0_.title as title2_0_0_ from Book2 book2x0_ |9 D" e& G, a0 W. |
- where book2x0_.id=?
/ O8 N+ {: W( a; x - com.xinglongjian.entity.hbm.Book2@521e083b
7 _9 R9 W" E1 k5 M$ b - SecondLevelCacheStatistics[hitCount=0,missCount=1,putCount=1,elementCountInMemory=1,elementC$ U& e- ^; o$ s6 |6 ^0 [
- ountOnDisk=0,sizeInMemory=1979]- \* t2 o n* }
- 1
4 l- d# j+ z& A! B$ T" w - --------------第二次查询后---------------------------------
/ b% s: \" U& r$ J, A2 Z - com.xinglongjian.entity.hbm.Book2@521e083b
- ]. v2 z8 Q, ?4 o) A9 P - SecondLevelCacheStatistics[hitCount=1,missCount=1,putCount=1,elementCountInMemory=1,elementC4 `' v$ o2 s6 l/ k: r2 r" c2 h2 M* B- M
- ountOnDisk=0,sizeInMemory=1979]5 l3 n4 U f8 M# ~! S
- --------------第三次查询后---------------------------------3 `0 I$ ?. M+ [. Y" X
- SecondLevelCacheStatistics[hitCount=2,missCount=1,putCount=1,elementCountInMemory=1,elementC t& i0 G" A4 l
- ountOnDisk=0,sizeInMemory=1979]
复制代码
: [5 E7 T, q) i, t ^4 S |
|