Hibernate二级缓存以及ehcache的搭建配置

转载自      https://blog.csdn.net/fengshizty/article/details/43603611

前言

        这次主要复习Hibernate的二级缓存的相关知识,配置以及使用。二级缓存主要采用第三方的ehcache,也将介绍ehcache缓存的相关配置属性以及在项目中的搭建,具体的项目查看下一篇的 Maven搭建SpringMVC+Hibernate项目详解 的文章。(之前使用过Hibernate的二级缓存,但是没自己搭建和研究过,现在花了半天时间搭建了一下,写下来供大家参考)

1、Hibernate二级缓存

     Hibernate包括两个级别的缓存:

        1、一级缓存:默认总是启用的session级别的。

         2、二级缓存:可选的SessionFactory级别的。

       Session级别的以及缓存总是有效的,当应用保持持久化实体、修改持久化实体时,Session并不会吧这种改变flush到数据库,而是缓存在当前Session的一级缓存中,除非程序显示调用session的flush方法,或者查询关闭session时,才会把这先改变一次性的flush到底层数据库,这样可以减少与数据库的交互,从而提高数据库的访问性能。

      SessionFactory级别的二级缓存是全局的,应用的所有的Seeion都共享这个二级缓存,当Session需要抓取数据时,Session就会优先从二级缓存中抓取。(主要包括实体缓存,查询缓存)。

2、适用范围

      主要适合以下数据放入二级缓存:

           1. 很少被修改,大量查询的

            2. 不是很重要的数据,允许出现偶尔并发访问的

3、Hibernate二级缓存的配置

              Hibernate的二级缓存主要使用第三方缓存插件,这里主要使用Ehcache二级缓存。

         首先、我们需要映入ehcache包以及hibernate-ehcache包,maven的pom.xml映入如下:

         

 1  
 2 <!-- hibernate -->
 3  
 4 <dependency>
 5  
 6 <groupId>org.hibernate</groupId>
 7  
 8 <artifactId>hibernate-core</artifactId>
 9  
10 <version>4.3.8.Final</version>
11  
12 </dependency>
13  
14  
15  
16 <dependency>
17  
18 <groupId>org.hibernate</groupId>
19  
20 <artifactId>hibernate-ehcache</artifactId>
21  
22 <version>4.3.8.Final</version>
23  
24 </dependency>
25  
26  
27  
28 <!-- 二级缓存ehcache -->
29  
30 <dependency>
31  
32 <groupId>net.sf.ehcache</groupId>
33  
34 <artifactId>ehcache</artifactId>
35  
36 <version>2.9.0</version>
37  
38 </dependency>


         其次、我们需要在Hibernate的配置文件中设置二级缓存的相关信息

                 

 1 <!-- 开启二级缓存 ehcache -->
 2  
 3 <prop key="hibernate.cache.use_second_level_cache">true</prop>
 4  
 5 <!-- 开启查询的二级缓存 如果不需要就不设置-->
 6  
 7 <prop key="hibernate.cache.use_query_cache">true</prop>
 8  
 9 <!-- Hibernate4.0以上设置factory -->
10  
11 <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
12  
13 <!-- 二级缓存 ehcache的配置文件位置 -->
14  
15 <prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</prop>

            一般Hibernate的二级缓存实体和属性的缓存映射,如果需要将查询数据也二级缓存,需要使用hibernate.cache.use_query_cache开启。

 

4、Ehcache的配置

      ehcache.xml的配置文件如下:

     

 1  
 2 <?xml version="1.0" encoding="UTF-8"?>
 3  
 4 <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
 5  
 6  
 7  
 8 <diskStore path="java.io.tmpdir/ehcache" />
 9  
10 <!-- DefaultCache setting. -->
11  
12 <defaultCache
13  
14 maxElementsInMemory="1000"
15  
16 eternal="false"
17  
18 timeToIdleSeconds="300"
19  
20 timeToLiveSeconds="300"
21  
22 maxElementsOnDisk="1000000"
23  
24 overflowToDisk="true"
25  
26 memoryStoreEvictionPolicy="LRU">
27  
28  
29  
30 </defaultCache>
31  
32  
33  
34 <!-- Special objects setting. -->
35  
36 <!--
37  
38 <cache
39  
40 name="org.andy.work.entity.AcctUser"
41  
42 maxElementsInMemory="2"
43  
44 memoryStoreEvictionPolicy="LRU"
45  
46 eternal="true"
47  
48 diskPersistent="false"
49  
50 overflowToDisk="false"
51  
52 maxElementsOnDisk="1000000" /> -->
53  
54  
55  
56  
57  
58  
59  
60 </ehcache>

第一段是配置默认的ehcache二级缓存信息,第二段是特殊的配置(需要配置特殊时)。

4.1、配置详解

    name:缓存名称。
    maxElementsInMemory:缓存最大个数。
    eternal:对象是否永久有效,一但设置了,timeout将不起作用。
    timeToIdleSeconds:设置对象在失效前的允许闲置时间(单位:秒)。仅当eternal=false对象不是永久有效时使用,可选属性,默认值是0,也就是可闲置时间无穷大。
    timeToLiveSeconds:设置对象在失效前允许存活时间(单位:秒)。最大时间介于创建时间和失效时间之间。仅当eternal=false对象不是永久有效时使用,默认是0.,也就是对象存活时间无穷大。
   overflowToDisk:当内存中对象数量达到maxElementsInMemory时,Ehcache将会对象写到磁盘中。
   diskSpoolBufferSizeMB:这个参数设置DiskStore(磁盘缓存)的缓存区大小。默认是30MB。每个Cache都应该有自己的一个缓冲区。
   maxElementsOnDisk:硬盘最大缓存个数。
   diskPersistent:是否缓存虚拟机重启期数据 Whether the disk store persists between restarts of the Virtual Machine. The default value is false.
   diskExpiryThreadIntervalSeconds:磁盘失效线程运行时间间隔,默认是120秒。
   memoryStoreEvictionPolicy:当达到maxElementsInMemory限制时,Ehcache将会根据指定的策略去清理内存。默认策略是LRU(最近最少使用)。你可以设置为FIFO(先进先出)或是LFU(较少使用)。
   clearOnFlush:内存数量最大时是否清除。 

   注:java.io.tmpdir目录为:C:\Users\登录用户\AppData\Local\Temp\(window环境中),所以上面在我的电脑下的目录如下(已经有缓存内容):

       

     当然存储位置我们可以随意的配置如:   <diskStore path="D:/ehcache" />  就是在D盘下的ehcache目录了。

5、配置需二级缓存实体和属性

      这里只介绍注解形式的,xml形式的不说了,大多数公司都用注解。

    在实体类和实体的那些集合属性上启用二级缓存使用

              @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)

   注:如果一个实体需要二级缓存,若该实体含有<set...>,<list...>等属性时,也必须要指定缓存策略。

       如下:

     

  1  
  2 package org.andy.work.entity;
  3  
  4  
  5  
  6 // Generated 2015-2-3 10:43:00 by Hibernate Tools 4.0.0
  7  
  8  
  9  
 10 import java.util.Date;
 11  
 12 import java.util.HashSet;
 13  
 14 import java.util.Set;
 15  
 16  
 17  
 18 import javax.persistence.Column;
 19  
 20 import javax.persistence.Entity;
 21  
 22 import javax.persistence.FetchType;
 23  
 24 import javax.persistence.Id;
 25  
 26 import javax.persistence.JoinColumn;
 27  
 28 import javax.persistence.JoinTable;
 29  
 30 import javax.persistence.ManyToMany;
 31  
 32 import javax.persistence.Table;
 33  
 34 import javax.persistence.Temporal;
 35  
 36 import javax.persistence.TemporalType;
 37  
 38  
 39  
 40 import org.hibernate.annotations.Cache;
 41  
 42 import org.hibernate.annotations.CacheConcurrencyStrategy;
 43  
 44  
 45  
 46 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
 47  
 48  
 49  
 50 /**
 51  
 52 * AcctUser generated by hbm2java
 53  
 54 */
 55  
 56 @Entity
 57  
 58 @Table(name = "acct_user", catalog = "work")
 59  
 60 @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
 61  
 62 public class AcctUser implements java.io.Serializable {
 63  
 64  
 65  
 66 /**
 67  
 68 *
 69  
 70 */
 71  
 72 private static final long serialVersionUID = 6980093847795726310L;
 73  
 74 private String id;
 75  
 76 private String nickName;
 77  
 78 private String telephone;
 79  
 80 private Date registerTime;
 81  
 82 private Set<AcctRole> acctRoles = new HashSet<AcctRole>(0);
 83  
 84  
 85  
 86 public AcctUser() {
 87  
 88  
 89  
 90 }
 91  
 92  
 93  
 94 public AcctUser(String id, String nickName) {
 95  
 96 this.id = id;
 97  
 98 this.nickName = nickName;
 99  
100 }
101  
102  
103  
104 public AcctUser(String id, String nickName, String telephone,
105  
106 Date registerTime, Set<AcctRole> acctRoles) {
107  
108 this.id = id;
109  
110 this.nickName = nickName;
111  
112 this.telephone = telephone;
113  
114 this.registerTime = registerTime;
115  
116 this.acctRoles = acctRoles;
117  
118 }
119  
120  
121  
122 @Id
123  
124 @Column(name = "id", unique = true, nullable = false, length = 36)
125  
126 public String getId() {
127  
128 return this.id;
129  
130 }
131  
132  
133  
134 public void setId(String id) {
135  
136 this.id = id;
137  
138 }
139  
140  
141  
142 @Column(name = "nick_name", nullable = false)
143  
144 public String getNickName() {
145  
146 return this.nickName;
147  
148 }
149  
150  
151  
152 public void setNickName(String nickName) {
153  
154 this.nickName = nickName;
155  
156 }
157  
158  
159  
160 @Column(name = "telephone")
161  
162 public String getTelephone() {
163  
164 return this.telephone;
165  
166 }
167  
168  
169  
170 public void setTelephone(String telephone) {
171  
172 this.telephone = telephone;
173  
174 }
175  
176  
177  
178 @Temporal(TemporalType.TIMESTAMP)
179  
180 @Column(name = "register_time", length = 19)
181  
182 public Date getRegisterTime() {
183  
184 return this.registerTime;
185  
186 }
187  
188  
189  
190 public void setRegisterTime(Date registerTime) {
191  
192 this.registerTime = registerTime;
193  
194 }
195  
196  
197  
198 @JsonIgnoreProperties(value={"acctUsers", "acctAuthorities"})
199  
200 @ManyToMany(fetch = FetchType.LAZY)
201  
202 @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
203  
204 @JoinTable(name = "acct_user_role", catalog = "work", joinColumns = { @JoinColumn(name = "user_id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "role_id", nullable = false, updatable = false) })
205  
206 public Set<AcctRole> getAcctRoles() {
207  
208 return this.acctRoles;
209  
210 }
211  
212  
213  
214 public void setAcctRoles(Set<AcctRole> acctRoles) {
215  
216 this.acctRoles = acctRoles;
217  
218 }
219  
220  
221  
222 }

5.1、缓存usage事务隔离机制

        Usage提供缓存对象的事务隔离机制有如下几种:

        (NONE, READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL)

      ehcache不支持transaction事务机制,但其他三种可以使用:

       read-only::

                 无需修改, 那么就可以对其进行只读 缓存,注意,在此策略下,如果直接修改数据库,即使能够看到前台显示效果,

             但是将对象修改至cache中会报error,cache不会发生作用。另:删除记录会报错,因为不能在read-only模式的对象从cache中删除。

      read-write: 

                   需要更新数据,那么使用读/写缓存 比较合适,前提:数据库不可以为serializable transaction isolation level(序列化事务隔离级别)

     nonstrice-read-write:

                  只偶尔需要更新数据(也就是说,两个事务同时更新同一记录的情况很不常见),也不需要十分严格的事务隔离,那么比较适合使用非严格读/写缓存策略。

6、使用查询缓存

      查询缓存所缓存的key值就是查询所使用的HQL或SQL语句,需要注意的是:查询缓存不仅要求所使用的HQL语句、SQL语句相同,甚至是要求所传入的参数也相同,Hibernate才能从缓存中查去数据。

   查询缓存有如下两步:

      1、查询缓存不不仅开启 hibernate.cache.use_query_cache

      2、还需要在查询时使用  setCacheable(true)

    

public List<AcctUser> findAll() {
 
List<AcctUser> acctUsers = this.getCurrentSession().createQuery("from AcctUser").setCacheable(true).list();
 
 
 
return acctUsers;

猜你喜欢

转载自www.cnblogs.com/kwaitfort/p/9491775.html