该用户从未签到
|
需要启动二级缓存,二级缓存的scope是sessionFactory。也就是说二级缓存的数据可以在由相同SessionFactory创建的多个Session中重用。5 c9 V# G7 _$ c1 V
; e ]/ ^4 Z! }首先,要在hibernate.cfg.xml中设置一个cache Provider,hibernate支持多个cache实现,有EHCache,OSCache等。在非分布式环境中可以选择默认的EHCache。添加ehcahe jar. {( j5 L, D; H' m
- <dependency>. o: h8 j) O) v4 L$ R$ H2 a" ~! e% a
- <groupId>org.hibernate</groupId>
/ p9 ]' @/ q. d7 ?& h# t - <artifactId>hibernate-ehcache</artifactId>
1 L% K% U) e$ a - <version>4.3.5.Final</version>3 X1 W# }1 e7 m
- </dependency>
复制代码- <hibernate-configuration>% Y- J% E' q- I) V j3 x
- <session-factory>
! ~" N9 P& F: A4 j- j - <property name="connection.driver_class">com.mysql.jdbc.Driver</property>
- W. s" H0 B- H5 F. u+ A4 q$ Y; P - <property name="connection.url">jdbc:mysql://localhost/test</property>
- x6 q# S* e9 [% L6 y/ d - <property name="connection.username">root</property>
& h3 X0 h' _" e5 K; Z# i - <property name="connection.password"></property>6 U( M* @& p. K% R" a: w+ L
- <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>$ T0 M$ U- j; T) O" m- m/ z, e
- <property name="hibernate.show_sql">true</property>
+ w9 k+ I" v o6 G' e - <property name="hibernate.hbm2ddl.auto">update</property>! p5 }. g4 j& `3 i; p5 |/ B! W
- <property name="hibernate.generate_statistics">true</property>
, r( C! Z1 x+ w4 e% k! |1 } - <property name="hibernate.cache.region.factory_class"># j8 p3 z% n6 p. {
- org.hibernate.cache.ehcache.EhCacheRegionFactory
4 |; M/ G6 u* H. K/ i8 {" I y3 T - </property>
8 Z. e1 M S) J4 I; n - <mapping class="com.xinglongjian.entity.hbm.Book2"/>
0 k( J! @, p" K; g - </hibernate-configuration>
复制代码
7 f K* w! \8 g( i) R$ v. b2 w- G 第二,通过ehcache.xml配置EHCache,该文件放置于classpath的根目录下。可以在该配置文件中设置将不同的对象存储在不同的regions。- <ehcache>; ~) [9 A8 X0 m2 @( F
- <diskStore path="c:/data/ehcache"/>
7 a: C0 L5 @, } - <defaultCache9 Y% z5 ]9 d9 m. c6 p$ H5 C5 v
- maxElementsInMemory="10"6 P3 |% A% c2 X8 I0 d& L
- eternal="false"
8 G, J8 c; `3 @1 l6 a* r - overflowToDisk="true"
1 x9 l) m/ M: G- @$ l# Y - timeToIdleSeconds="120"+ ]0 G4 G5 a# a% {7 [/ }: `
- timeToLiveSeconds="120" e. z- w$ g7 p6 I* n
- diskPersistent="false"
! Q6 L; X' F8 E; d" \ - diskExpiryThreadIntervalSeconds="120"/>
5 ~9 v& i: T5 O- W* R - <cache name="com.xinglongjian.entity.hbm.Book" maxElementsInMemory="10" eternal="false" 6 c' G: `8 n# L, C- F
- overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskPersistent="false"/>0 h9 ~4 h' ^1 b3 R, c' j5 e# ]# U5 W
- </ehcache>
复制代码 第三,设置持久化类- @Entity! x, m0 g a9 W& r
- @Cacheable
, K" R* b1 S5 y: q/ E - @Cache(usage=CacheConcurrencyStrategy.READ_ONLY,region="com.xinglongjian.entity.hbm.Book")
9 Q4 e3 h3 P, Y: B; M1 N - public class Book2 { k8 @- E/ h2 o3 n% \2 x' f0 N
- @Id
; w7 u, O9 W4 U7 d9 g - @GeneratedValue' w: |/ H) P, L9 p
- private int id;" q, [; j2 D# y0 c
- private String title;+ g6 e% E% P, q+ `
- public String getTitle() {6 B7 a, }4 H2 J) \- p/ a
- return title;
+ o4 L& m5 m" Z5 ` - }. K1 S7 X' d- I5 O( i
- public void setTitle(String title) {4 T/ }4 c1 P$ c p1 S2 z$ ^
- this.title = title;
) |2 Y) K& Y5 I, k - }
3 Y; t- U) v* `4 \3 ?, d - public int getId() {
+ |* e. z4 ?$ ]* J - return id;! `9 i& Y M! r
- }
1 _ v9 Q0 y$ B# B - public void setId(int id) {, H2 I3 ^7 M1 U' B. V7 t
- this.id = id;
& A+ P) v9 O' g* ]! x2 H7 ^ - }
9 K1 Q4 J' H u* X - @Override0 A1 O d# ?: ]
- public int hashCode() {
0 k1 D6 x" ] q E/ `6 s - final int prime = 31;2 f5 ~6 w7 m! L n9 |
- int result = 1;2 _$ u4 r3 y+ x0 t* n5 j
- result = prime * result + id;
! Q! _$ V1 x& U1 p' A$ R5 z - result = prime * result + ((title == null) ? 0 : title.hashCode());
9 ]' }( h8 d C6 F0 S! M w8 { - return result;) h( I& s; k) n1 H: `! m
- }
& T" @7 L2 X4 s9 T$ O0 r - @Override
( b2 @, d* T$ ?5 h n - public boolean equals(Object obj) {
. E; H" D3 T& k9 W2 ?( D - if (this == obj)
: @; V# K! k; o - return true;: F: W& n9 d2 F- r8 d
- if (obj == null)
! ?6 Z8 w1 w" v9 g9 y4 C) |8 G - return false;
- W b) t. @+ G& _( n - if (getClass() != obj.getClass())6 v/ ?0 x2 J8 R# Q2 F* V0 r* m
- return false;
6 i- E% {* ^4 X" T - Book2 other = (Book2) obj;8 H5 |. c' q+ }+ ?4 C8 l6 l; G2 o
- if (id != other.id)
( Z& N. }. B1 X; K" z - return false;5 v; p; @7 @6 S( [, k$ Q1 X, u# v4 b
- if (title == null) {
& }8 G4 C+ e: `5 @. B# ~; I% Z - if (other.title != null)7 U. l: w6 U6 L1 p$ ^8 t5 v
- return false;
9 Z3 z R! \, ` - } else if (!title.equals(other.title))8 c# a6 ?% V, I; _, [7 W9 a- ?
- return false;
( h8 @( b- a9 i/ U- J1 P0 k& w8 p - return true;7 @3 v5 H( \7 v- f. |7 {$ s
- }
. q) `6 b* x2 O1 N2 x4 E% O0 T - ( y+ W- x/ r! W8 z
- }
复制代码 二级缓存的持久化类必须实现equals方法。
7 i+ g6 D' E! H( W$ a9 M$ w& O7 G" M. U8 r
只有在SELECT时才会缓存。# O* p- Z% |" C; }) o
, `: u* _6 ^+ v/ @在同一个session里,查询2个不同的对象,会缓存2次,- Session sess=sf.openSession();& y8 j% S4 C2 D! U2 T
- Book2 b=(Book2) sess.get(Book2.class, 17);$ N$ q' u' S* v6 E0 y
- System.out.println(b);
+ W" ^* R- I$ U7 t3 Y1 q( w5 H - assertEquals("spring Recipes", b.getTitle());/ u/ S4 G5 {6 Y# V+ `5 c v; x
- Book2 b3=(Book2) sess.get(Book2.class, 18);
9 ]5 l1 N, t9 ^ - assertEquals("dfad", b3.getTitle());
$ k/ l" p( Y0 U' E - sess.close();+ X J+ @6 K6 F2 d a7 z2 J# Y
- slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");0 X, D5 E& T2 @# Z. t1 V
- System.out.println(slcs);
复制代码 结果- SecondLevelCacheStatistics[hitCount=0,missCount=2,putCount=2,elementCountInMemory=2,elementC4 s1 w7 n1 B4 z4 {
- ountOnDisk=0,sizeInMemory=3948]
复制代码 / W$ P3 a; V: ]$ \2 f; U1 x
在同一个session里,查询相同的对象,会先查询一级缓存,一级缓存中有就不会查询二级缓存。- Session sess1=sf.openSession();: v) H4 D+ P" A( ]2 V. N
- Book2 b1=(Book2) sess1.get(Book2.class, 17);
+ T3 O6 z' M1 Y; X! k! E7 L - System.out.println(b);$ y$ H2 y5 S5 `9 H
- Book2 b2=(Book2) sess1.get(Book2.class, 17);
* g- S1 `; j8 C& r! W - assertEquals("Spring Recipes", b1.getTitle());
5 s6 U' |2 B' P% `- ~) b% I8 M - assertEquals("Spring Recipes", b2.getTitle());
4 x- V+ ? V( n - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
% h6 |* B6 J* s0 i+ i - System.out.println(slcs);
复制代码 结果,在新的session中,一级缓存不可用,就会使用二级缓存。- SecondLevelCacheStatistics[hitCount=1,missCount=2,putCount=2,elementCountInMemory=2,elementC/ k. a( h& a: |3 v! b6 e7 [" t$ U
- ountOnDisk=0,sizeInMemory=3948]
复制代码 完整测试逻辑- @Test
& }# n" D0 q) J5 m; q, ~ - public void test2LCache()
7 E3 x7 L7 j! O# W; s - {
+ Q& E0 z4 G; }6 _ - Statistics stat=sf.getStatistics();//获取stat对象; P+ ?, B! Y# ]. i. H. B
- Session sess=sf.openSession();
8 Q+ _1 n6 Z# _" q! ?% U - Transaction tx=sess.beginTransaction();7 x* W, F- r/ t- y# E) G
- 2 l) ]+ _# g8 b) C, \
- //存储对象,此时不会放到缓存中
! N8 `7 d. N% ^ - System.out.println("--------------存储对象---------------------------------");# @% m- Q6 f" k+ c5 X
- Book2 book=new Book2();
# o; Y2 T# h# N$ z - book.setTitle("Spring Recipes");5 r. B: k9 @8 ^, o, P0 c0 F( y
- sess.saveOrUpdate(book);# x7 l0 w% H+ \
- tx.commit();
! D/ m; X3 K+ i- g - sess.close();: |# B& M7 R, Q3 Q, D
- System.out.println(book);
( Y* H( b; w% k# c- n% \ - SecondLevelCacheStatistics slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");; B0 R7 V2 f4 L" D, b6 X4 M3 i
- System.out.println(slcs);1 n( {, C$ h3 Q) x
- Cache cache=sf.getCache();: k3 F+ } ]; ]
- System.out.println(cache);$ |% |! U' [& Z$ g- C* ]: E) F
- cache.evictAllRegions();//从所有region中获取数据
' D! h5 _, ~: Z) J" W! Z - Map map=slcs.getEntries();- v" y% I/ m( y1 e4 |
- System.out.println("Cache entries:"+map.size());
$ u* |0 y* d! J- J3 x - System.out.println("--------------第一次查询后---------------------------------");/ t& M/ r) `8 P' N
- sess=sf.openSession();
' \ f( L6 @8 {7 j0 f - tx=sess.beginTransaction(); r8 B' f, o& {4 e5 ^3 Y
- Book2 b1=(Book2) sess.byId(Book2.class).load(book.getId());//第一次查询) z% w3 y! y0 B2 `2 M
- System.out.println(b1);$ x& d& L: ]8 D; I3 ~
- assertEquals(book, b1);( b5 g d9 @% [3 N4 n) o
- tx.commit();6 |) L1 s' w4 O
- sess.close();
8 ]5 a4 Q/ \# k3 t3 u - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");9 \- J. a' P& v8 @, F
- System.out.println(slcs);
) y: W1 |8 o- u - map=slcs.getEntries();5 x; k: |: W z, t6 D; h$ t7 b
- System.out.println(map.size());
% P1 o# e/ _; {1 x9 J$ l - System.out.println("--------------第二次查询后---------------------------------");
: _ q2 D- z( A* n* @- N* b - sess=sf.openSession();
, X+ H ?; [8 L - tx=sess.beginTransaction(); l$ |4 Y5 L- @ S7 H) r
- Book2 b2=(Book2) sess.byId(Book2.class).load(book.getId());//第二次查询' W" r! a+ q+ @* i8 s$ k# i8 b
- System.out.println(b2);" V. u) L% A6 G% M0 V2 t! a
- assertEquals(book, b2);* r5 X+ p8 J+ S C5 U1 i! t1 {& N
- tx.commit();# ^4 ]* l& `( f; z' @6 @) U8 S: T
- sess.close();7 p2 X" C- I# ?: X9 L* i# |2 `
-
, V% o9 B ~: {3 T2 k3 W& i - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
" b% i3 y) v9 a& }' ]2 w1 v( r5 D - System.out.println(slcs);
2 s* d; ` a/ R3 D - // this is the initial select3 A4 P7 F- v4 V9 F* z4 N: v( Q; L' X
- assertEquals(stat.getSecondLevelCacheMissCount(), 1);
1 V& H ?8 n/ P: g- ~ - // we put one element in the cache from the miss1 Z% R4 Y8 y5 O/ \; e3 {
- assertEquals(stat.getSecondLevelCachePutCount(), 1);
' P1 k' @5 _1 F6 O# k0 E - // we still didn't hit the cache, because of 1L cache
% u& ?9 b7 I& j5 c. y$ H* q - assertEquals(stat.getSecondLevelCacheHitCount(), 1);
- |3 \, g5 W( `. Y. g! G$ u2 X - System.out.println("--------------第三次查询后---------------------------------");4 H9 G: n% P" M L; J" Y
- sess=sf.openSession();; z% Q# g: d0 N3 m( d
- tx=sess.beginTransaction();
/ W$ s! q: h s* M3 q2 F - b1=(Book2) sess.byId(Book2.class).load(book.getId());//第三次查询6 C% Q' I b" i7 J/ M3 c
- assertEquals(book, b1);
7 ~; Y5 z3 }) H$ k" } - tx.commit();
n) s7 l5 w( ~9 ^ - sess.close();0 a4 C4 _2 C% N1 _) X7 b
-
9 `' T9 R% M2 s: e4 A Y - slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");9 C. J& X( L+ c5 `- V
- System.out.println(slcs);$ k! [: G$ x) [. V3 b# `. ?
- // same miss count (we should hit now)
. T. D8 A' L/ D1 o% d4 {- L - assertEquals(stat.getSecondLevelCacheMissCount(), 1);
8 |5 t( G4 z# }! w% D# {: X. @ - // same put count (we didn't put anything new)
5 O- X, W o3 Z/ J% `: L - assertEquals(stat.getSecondLevelCachePutCount(), 1);6 E2 ]' _4 h- F2 k
- // now we hit the 2L cache for load0 P) J' Z; F) c' f; i0 c0 D
- assertEquals(stat.getSecondLevelCacheHitCount(), 2);4 U+ A" i0 e: x8 [5 [8 \
- ! {, m- \8 A% t! O
- }
复制代码 完整测试结果- Hibernate: delete from book2) m, p8 }( w$ v5 b. ?* L
- --------------存储对象---------------------------------# k( T3 ~" V3 W. q8 }
- Hibernate: insert into Book2 (title) values (?)- K! a5 J9 B( F( h4 q7 y
- com.xinglongjian.entity.hbm.Book2@521e083b( f3 l$ ^ u- P$ x" `
- SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=0,elementCountInMemory=0,elementCountOnDisk=0,sizeInMemory=0]
$ b0 m& S( w0 T' ^3 b - org.hibernate.internal.CacheImpl@4830f6
/ o& L* a/ L8 g8 I1 L - Cache entries:0
5 X: o9 N8 A/ A - --------------第一次查询后---------------------------------
$ {; G# z* ~$ U" y3 @% l F - Hibernate: select book2x0_.id as id1_0_0_, book2x0_.title as title2_0_0_ from Book2 book2x0_
i7 U( n3 x& O& f0 f( O% l - where book2x0_.id=?
& b; k) f8 h4 C - com.xinglongjian.entity.hbm.Book2@521e083b( i/ R3 Z& |# Y7 l. |
- SecondLevelCacheStatistics[hitCount=0,missCount=1,putCount=1,elementCountInMemory=1,elementC
5 V: l. L, c& |. T5 q - ountOnDisk=0,sizeInMemory=1979]3 J+ K: g; Y! r& z, U) \ v
- 1
/ d# S! y& x1 z& G% [) y6 E - --------------第二次查询后---------------------------------. f# b& m o& r. M) [
- com.xinglongjian.entity.hbm.Book2@521e083b
# D( k% u' j$ W - SecondLevelCacheStatistics[hitCount=1,missCount=1,putCount=1,elementCountInMemory=1,elementC
& G |( z. t% @& U) _: [ - ountOnDisk=0,sizeInMemory=1979]3 @! @0 z- {/ `7 f3 o4 m1 {& d' k: l
- --------------第三次查询后---------------------------------& w( }2 }) b% [8 d$ Z6 D
- SecondLevelCacheStatistics[hitCount=2,missCount=1,putCount=1,elementCountInMemory=1,elementC, ^! b7 b0 j) ]0 f |
- ountOnDisk=0,sizeInMemory=1979]
复制代码
$ i: T5 B9 K- W' D |
|