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;
posted on 2018-08-17 10:05 wait_for_you 阅读(655) 评论(0) 编辑 收藏 举报