我的日常

登录/注册
您现在的位置:论坛 盖世程序员(我猜到了开头 却没有猜到结局) 盖世程序员 > 如何配置Hibernate中的二级缓存
总共48086条微博

动态微博

查看: 1069|回复: 0

如何配置Hibernate中的二级缓存

[复制链接]

279

主题

41

听众

689

金钱

版主

该用户从未签到

跳转到指定楼层
#
发表于 2015-07-18 22:13:11 |只看该作者 |正序浏览
需要启动二级缓存,二级缓存的scope是sessionFactory。也就是说二级缓存的数据可以在由相同SessionFactory创建的多个Session中重用。
: \( _% S" `0 R4 W/ E2 A& t( j& W! [) f
首先,要在hibernate.cfg.xml中设置一个cache Provider,hibernate支持多个cache实现,有EHCache,OSCache等。在非分布式环境中可以选择默认的EHCache。添加ehcahe jar7 w) X4 V) N+ B, }
  1. <dependency>/ }& x" ^- f- }
  2.           <groupId>org.hibernate</groupId>
    ( W1 T) p6 K1 U* f
  3.           <artifactId>hibernate-ehcache</artifactId>$ v: e2 R4 i0 W0 N4 h8 \" `, U
  4.           <version>4.3.5.Final</version>
    " e( `2 T# t$ I5 q  y/ Y# S4 x9 M
  5.       </dependency>
复制代码
  1. <hibernate-configuration>  X! c% S7 \5 Z, V6 e4 @
  2.     <session-factory>! e; B* e7 G% O7 i4 G; o
  3.         <property name="connection.driver_class">com.mysql.jdbc.Driver</property>2 W( T) a6 O  B5 ?
  4.         <property name="connection.url">jdbc:mysql://localhost/test</property>) f3 {+ u  I9 Y: [/ k( ^: r2 A
  5.         <property name="connection.username">root</property>
    # r* z+ W$ \9 K% O
  6.         <property name="connection.password"></property>" j) ^4 Q- T4 Q; i
  7.         <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property># j* C" H6 h; P# Z
  8.         <property name="hibernate.show_sql">true</property>
    8 q& U. E# y2 Q; S9 l/ D9 N/ B
  9.         <property name="hibernate.hbm2ddl.auto">update</property>8 \1 F# y) M( O* v& a
  10.         <property name="hibernate.generate_statistics">true</property>  p) y0 d1 I& |" A
  11.         <property name="hibernate.cache.region.factory_class">
    ; V; c) _& z; t; s) F7 {
  12.             org.hibernate.cache.ehcache.EhCacheRegionFactory" H7 d: P7 O# O/ z0 F2 n
  13.         </property>- D1 F$ n6 h* v4 ^
  14.         <mapping class="com.xinglongjian.entity.hbm.Book2"/>
    : }# C0 e0 k7 g# v' |- _+ Z, [
  15. </hibernate-configuration>
复制代码

% Z8 G# ?; z; n: _. ^( H8 b6 t' Y 第二,通过ehcache.xml配置EHCache,该文件放置于classpath的根目录下。可以在该配置文件中设置将不同的对象存储在不同的regions。
  1. <ehcache>& |2 a2 c3 I# c0 x* D- `" J! K* Y8 j
  2. <diskStore path="c:/data/ehcache"/># e6 G9 Z6 M7 I/ B/ [6 c2 g
  3. <defaultCache: G% n7 [; Z& a) R/ `4 }+ z
  4.         maxElementsInMemory="10"
    4 f$ S& @: y- z. L1 V) q, H
  5.         eternal="false"
    : S& @, ~. B1 C9 ?% k$ u
  6.         overflowToDisk="true"
    ! _$ I& K" u& O+ D
  7.         timeToIdleSeconds="120"- m, p5 c) s, G; c+ I5 W0 l
  8.         timeToLiveSeconds="120"; r2 R# J% i; O$ A- s8 d1 e
  9.         diskPersistent="false"
    % o8 \8 E2 F8 o0 B, o
  10.         diskExpiryThreadIntervalSeconds="120"/>
    6 T; k- f- {8 x) n
  11. <cache name="com.xinglongjian.entity.hbm.Book" maxElementsInMemory="10"  eternal="false"
    0 n# e" J$ L( A
  12.     overflowToDisk="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskPersistent="false"/>
    " i4 |$ `) [2 q3 V5 f/ E( L% _
  13. </ehcache>
复制代码
第三,设置持久化类
  1. @Entity
    5 v8 D! P3 Z2 w1 }( }! H" U
  2. @Cacheable
    ( j5 \/ O2 l- g
  3. @Cache(usage=CacheConcurrencyStrategy.READ_ONLY,region="com.xinglongjian.entity.hbm.Book")# S/ K  s' Y! _# a
  4. public class Book2 {# r: |% a+ U7 p" I3 D! q
  5.     @Id
    & a5 S' X/ w8 n
  6.     @GeneratedValue! A0 E* T  N( E( L' s5 }! c
  7.     private int id;
      z3 o" I0 B9 b# {
  8.     private String title;
    8 n' h, J7 I4 n& K5 h! s
  9.     public String getTitle() {
    8 r9 ?. d- X; U9 n
  10.         return title;3 |) \4 g* _" `& O- m- h
  11.     }
    & O) G2 f9 L5 D5 L2 o% Y
  12.     public void setTitle(String title) {1 A  M% v, W: T: g0 j
  13.         this.title = title;
    / s' f; M( r6 |5 s9 E* u  Z6 A
  14.     }- l8 [0 L# f6 ^, }
  15.     public int getId() {% I8 o, X" J- i2 d& S! Q7 ^5 E
  16.         return id;8 }1 p: G* i* B6 t
  17.     }
    5 x7 x' ]+ T3 ?) @; s3 F) ~
  18.     public void setId(int id) {
    : x* s+ c2 C5 z: N! R' t) S, ]
  19.         this.id = id;
    3 Z7 F; O0 H/ K
  20.     }
    7 f9 y. p8 `( M! ?
  21.     @Override
    ; N( V- n% I7 K
  22.     public int hashCode() {" x3 w  B( c- w2 N: u3 J) x* N
  23.         final int prime = 31;7 L6 j: C& F3 L
  24.         int result = 1;
    * B" |$ @3 p" o; r/ A( G9 y" F# O
  25.         result = prime * result + id;
    2 h' j  U& b2 [; Z# X: Q
  26.         result = prime * result + ((title == null) ? 0 : title.hashCode());9 E5 y( ~3 f/ y2 j* y% h
  27.         return result;
    + h( A1 }$ c( p# c9 K" ~9 Z! b
  28.     }" }  |* }- s1 z" q. f
  29.     @Override8 `4 [' s; E  @' _" e$ |
  30.     public boolean equals(Object obj) {8 I( \- n! S( ]
  31.         if (this == obj)
    % y( f( X5 S* X9 p6 u" o8 V
  32.             return true;
    " }' V, Y  ~. J
  33.         if (obj == null)
    ( M6 e' i! w9 J$ p
  34.             return false;
    5 B  d7 [. e0 N2 g/ H& H" a
  35.         if (getClass() != obj.getClass())2 j% c; {* `( d
  36.             return false;
    + a4 U. j9 k8 K1 Q. I
  37.         Book2 other = (Book2) obj;
    $ [! z% n8 E* j' h1 M& h1 Q0 v5 j' P
  38.         if (id != other.id)8 u. J3 p- S4 d# k3 ~/ W2 K: m+ Q
  39.             return false;
    5 l& v* x; \3 h5 t2 e: t/ e  k
  40.         if (title == null) {. P. G* C1 q7 O: f* e1 c. p
  41.             if (other.title != null)6 w' `+ J$ ?* x, k  X' H0 n
  42.                 return false;6 f9 s0 P2 v9 ]& W3 Y
  43.         } else if (!title.equals(other.title))
      y0 _, L. N3 y1 H  M
  44.             return false;
    8 M# _3 @# h. k
  45.         return true;& O3 X1 C: h; R
  46.     }( K7 W  x, D- h* w
  47.    
    1 p8 ^5 g+ H& _( g4 }& }
  48. }
复制代码
二级缓存的持久化类必须实现equals方法。; r2 t1 U7 Z* E* d
4 m; M9 ?. c$ u- S0 c  Q
只有在SELECT时才会缓存。: T3 m+ N; q  [2 w3 P) E5 C

# G3 d, L; K8 B  X在同一个session里,查询2个不同的对象,会缓存2次,
  1. Session sess=sf.openSession();
    . l. G; a7 L, ~% t& }7 Q8 E( h
  2.         Book2 b=(Book2) sess.get(Book2.class, 17);2 w' G: @. e& |, S$ ^# ?
  3.         System.out.println(b);  Q! O3 B/ G2 m, o0 R) x
  4.         assertEquals("spring Recipes", b.getTitle());, l6 c6 j; [! W* d4 y
  5.         Book2 b3=(Book2) sess.get(Book2.class, 18);
    , k/ {$ v( y3 K, {- s" X
  6.         assertEquals("dfad", b3.getTitle());
    ! H: h) y, j7 H# ^
  7.         sess.close();
    # H9 Q3 p. q: X1 y* ^0 p' b
  8.         slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");" o# g8 M) I" j" c
  9.         System.out.println(slcs);
复制代码
结果
  1. SecondLevelCacheStatistics[hitCount=0,missCount=2,putCount=2,elementCountInMemory=2,elementC) F2 q, m# j! I5 n# N; I: T
  2. ountOnDisk=0,sizeInMemory=3948]
复制代码

( }4 \/ S8 u7 o' A" d' U 在同一个session里,查询相同的对象,会先查询一级缓存,一级缓存中有就不会查询二级缓存。
  1. Session sess1=sf.openSession();5 i# r5 Q3 W" a0 X% u2 X6 s
  2.         Book2 b1=(Book2) sess1.get(Book2.class, 17);
    ; p" r$ X& e4 |
  3.         System.out.println(b);
    9 K# t- C  t# A' ?5 `  s- i: k' C
  4.         Book2 b2=(Book2) sess1.get(Book2.class, 17);7 y( L/ x5 M) Q- ^) D2 l" n
  5.         assertEquals("Spring Recipes", b1.getTitle());
    . R: B! r' r' C+ n" A
  6.         assertEquals("Spring Recipes", b2.getTitle());
    8 A" h$ m9 q; d/ w0 L: e' B8 Z- z% l
  7.         slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");3 x8 ^" H! U1 f" h1 \
  8.         System.out.println(slcs);
复制代码
结果,在新的session中,一级缓存不可用,就会使用二级缓存。
  1. SecondLevelCacheStatistics[hitCount=1,missCount=2,putCount=2,elementCountInMemory=2,elementC
    % B& b, n* b; v' ]' J
  2. ountOnDisk=0,sizeInMemory=3948]
复制代码
完整测试逻辑
  1. @Test
    ! h- j6 E3 P5 W* J+ L' Q
  2.     public void test2LCache()
    3 J! g- y* ?9 f+ ]1 _  i; O
  3.     {/ {: R6 x( O7 H' ]
  4.         Statistics stat=sf.getStatistics();//获取stat对象7 E: h" G) M; u. c
  5.         Session sess=sf.openSession();2 ?# u  X; d4 A* [7 [
  6.         Transaction tx=sess.beginTransaction();, _7 u' \' ^- I
  7.         8 ]; L- @/ X0 K" w" X! D
  8.         //存储对象,此时不会放到缓存中+ v9 w" b4 P8 j
  9.         System.out.println("--------------存储对象---------------------------------");/ {2 x- _4 V0 o. A
  10.         Book2 book=new Book2();
    . U0 H9 w3 r* I) g+ H
  11.         book.setTitle("Spring Recipes");- U7 b5 z# W& `6 n! [0 ?: {8 G
  12.         sess.saveOrUpdate(book);
      \4 @- Q- F% L2 z9 l6 o
  13.         tx.commit();
    6 A5 F/ _8 r  e+ I
  14.         sess.close();
    7 I2 ^/ d% `% @. Z0 [* R6 d  a( L
  15.         System.out.println(book);
    5 S( J- _5 d* L7 j5 Z
  16.         SecondLevelCacheStatistics slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
    - {* t7 B% ]4 p* [( \* w! x
  17.         System.out.println(slcs);
    / j0 W  J$ `  s9 T& ?
  18.         Cache cache=sf.getCache();5 a. ?: v# a- P9 b6 ]0 t" s% A
  19.         System.out.println(cache);# }& X$ W+ C4 ?+ W3 F* g5 n8 F
  20.         cache.evictAllRegions();//从所有region中获取数据
      g5 v2 g0 ?3 Y; l, \
  21.         Map map=slcs.getEntries();
    5 O, J6 ~8 U( I: K
  22.         System.out.println("Cache entries:"+map.size());
    4 {" H% b2 E" y9 i& I" }9 U
  23.         System.out.println("--------------第一次查询后---------------------------------");
    : ^" V! j1 }0 t, y
  24.         sess=sf.openSession();' _5 p$ E5 K" b# C
  25.         tx=sess.beginTransaction();( W6 u  Y( A4 M: b# D' N5 \
  26.         Book2 b1=(Book2) sess.byId(Book2.class).load(book.getId());//第一次查询
    & d7 l# ~/ Y; A4 M# D! M
  27.         System.out.println(b1);
    / W" ]9 C4 A4 h
  28.         assertEquals(book, b1);( u, b* [0 A4 n1 i6 f  ^
  29.         tx.commit();
    : m" e8 _; z8 ^3 ?* l. o
  30.         sess.close();% J3 t% L: o. t& l+ I4 ^
  31.         slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");( ?( q8 H. b% \" w
  32.         System.out.println(slcs);2 Y: T6 U8 z- s9 o3 Z. e# E
  33.         map=slcs.getEntries();
    2 k/ ^' W0 ~; Z7 {: M
  34.         System.out.println(map.size());, L: a! P* d1 C8 a* z% L' b
  35.         System.out.println("--------------第二次查询后---------------------------------");
    " i8 x. Q( `% ~- V7 {, R. ?5 a* `
  36.         sess=sf.openSession();( r/ l  y3 ]5 B; R3 W% ^
  37.         tx=sess.beginTransaction();
    4 H! g( [8 A% ?/ |# V4 s* \- H
  38.         Book2 b2=(Book2) sess.byId(Book2.class).load(book.getId());//第二次查询( v* F0 M5 {3 G! z
  39.         System.out.println(b2);
    & z7 m+ Z+ V: n
  40.         assertEquals(book, b2);8 p  [. j9 f" n6 Z: T
  41.         tx.commit();
    ) z6 ?6 v4 A1 l4 d1 m
  42.         sess.close();8 r: V1 F" K8 l* ^
  43.         
    * W) Q7 K3 B8 s/ _/ g
  44.         slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
      L2 b. ?- ]2 q$ q
  45.         System.out.println(slcs);" B2 b/ I$ B/ s' Z8 F2 u: ?3 E" I
  46.         // this is the initial select
    - }' o3 u* A9 I4 N6 k1 w1 |' f
  47.         assertEquals(stat.getSecondLevelCacheMissCount(), 1);
    4 e* y; |7 `& O. p2 q3 d
  48.         // we put one element in the cache from the miss
    - G8 ^% K4 L9 E
  49.         assertEquals(stat.getSecondLevelCachePutCount(), 1);/ V' v$ i: |& R) J3 h
  50.         // we still didn't hit the cache, because of 1L cache
    * k0 P3 R6 ]7 G+ q$ ^3 l
  51.         assertEquals(stat.getSecondLevelCacheHitCount(), 1);
    8 E$ {7 r0 F& h3 F
  52.         System.out.println("--------------第三次查询后---------------------------------");, M7 d$ D  m( D8 u
  53.         sess=sf.openSession();7 {6 a+ g! [% `- g
  54.         tx=sess.beginTransaction();  Y* I3 R# w, C$ {. ?/ `  `# E6 ^+ U
  55.         b1=(Book2) sess.byId(Book2.class).load(book.getId());//第三次查询
    * U" {5 T0 R6 G: J0 L
  56.         assertEquals(book, b1);* [; U: y  S0 H
  57.         tx.commit();
    % z6 }' Z/ q8 Y: z1 g" e: [; V. u
  58.         sess.close();
    9 x1 k5 n; [3 q1 n. F7 @' T
  59.         
    5 u# {9 a% G) D
  60.         slcs=stat.getSecondLevelCacheStatistics("com.xinglongjian.entity.hbm.Book");
    * [7 V! d( F9 Z4 k
  61.         System.out.println(slcs);
    0 n. T+ f/ [1 _8 a/ V
  62.         // same miss count (we should hit now)
    3 m$ k) v  P* [
  63.         assertEquals(stat.getSecondLevelCacheMissCount(), 1);/ O& L6 Q$ ^4 _( x
  64.         // same put count (we didn't put anything new)* h; N; j0 O  P7 A
  65.         assertEquals(stat.getSecondLevelCachePutCount(), 1);
    9 j* Z) E; n. d& f# h9 H
  66.         // now we hit the 2L cache for load9 J; {% d# X! d3 c, O& Q
  67.         assertEquals(stat.getSecondLevelCacheHitCount(), 2);
    : Q' }5 f8 @$ t2 {$ L; A# E' L6 G% s
  68.         9 a  z4 }; D; k
  69.     }
复制代码
完整测试结果
  1. Hibernate: delete from book2
    ; \' ~, h7 t3 K9 ?- T. w: V
  2. --------------存储对象---------------------------------( t3 O$ Z4 B% M* Z4 I
  3. Hibernate: insert into Book2 (title) values (?)7 w5 [6 O: R$ z/ X& Q' i
  4. com.xinglongjian.entity.hbm.Book2@521e083b
    , _' [* X1 Q$ E9 n/ y. c
  5. SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=0,elementCountInMemory=0,elementCountOnDisk=0,sizeInMemory=0]
    1 E! ~; ?* Z2 x' ^1 J! {0 p1 g
  6. org.hibernate.internal.CacheImpl@4830f6
    0 ?$ U- ?( b4 g0 ]
  7. Cache entries:0
    & a3 Q) q& h( K* v0 p
  8. --------------第一次查询后---------------------------------8 h: f2 s  x5 x0 G
  9. Hibernate: select book2x0_.id as id1_0_0_, book2x0_.title as title2_0_0_ from Book2 book2x0_% L) s- \% m( M* ^$ D. u
  10. where book2x0_.id=?9 X9 D- Y4 q8 @& _1 }2 C
  11. com.xinglongjian.entity.hbm.Book2@521e083b$ i" Y" l, I) x) [. }
  12. SecondLevelCacheStatistics[hitCount=0,missCount=1,putCount=1,elementCountInMemory=1,elementC
    ; I( p8 y9 r0 z* @' H+ T) Y
  13. ountOnDisk=0,sizeInMemory=1979]
    ! j( u) X+ j' F$ p. g  [1 d) g
  14. 1
    2 y' z3 g8 o2 {: {- U) `3 M. J9 t& b
  15. --------------第二次查询后---------------------------------' k$ c7 g9 ^4 Z
  16. com.xinglongjian.entity.hbm.Book2@521e083b
    5 ^! B# k6 [6 A. H- b5 R
  17. SecondLevelCacheStatistics[hitCount=1,missCount=1,putCount=1,elementCountInMemory=1,elementC
    + x& s, [' m$ }2 M
  18. ountOnDisk=0,sizeInMemory=1979]9 P1 U3 k7 b' g) r% c
  19. --------------第三次查询后---------------------------------
    # ^% C' Z! p8 O. m/ P
  20. SecondLevelCacheStatistics[hitCount=2,missCount=1,putCount=1,elementCountInMemory=1,elementC+ K: H) }: O5 E
  21. ountOnDisk=0,sizeInMemory=1979]
复制代码

4 i+ W5 G* j- |3 A

科帮网 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关
2、本站所有主题由该帖子作者发表,该帖子作者与科帮网享有帖子相关版权
3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网的同意
4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
7、科帮网管理员和版主有权不事先通知发贴者而删除本文


JAVA爱好者①群:JAVA爱好者① JAVA爱好者②群:JAVA爱好者② JAVA爱好者③ : JAVA爱好者③

快速回复
您需要登录后才可以回帖 登录 | 立即注册

   

关闭

站长推荐上一条 /1 下一条

发布主题 快速回复 返回列表 联系我们 官方QQ群 科帮网手机客户端
快速回复 返回顶部 返回列表