Hibernate EHCache Second Level Cache Example
2016-06-04 00:00
731 查看
摘要: 了解过Hibernate都知道,Hibernate本身不提供二级缓存的实现,而是使用第三方的缓存产品,比如EHCache等等,这个实例就是讲讲hibernate和EHCache的整合。
说明一下上面的一些配置项:
name:cache唯一标识
eternal:缓存是否永久有效
maxElementsInMemory:内存中最大缓存对象数
overflowToDisk(true,false):缓存对象达到最大数后,将缓存写到硬盘中
diskPersistent:硬盘持久化
timeToIdleSeconds:缓存清除时间
timeToLiveSeconds:缓存存活时间
memoryStoreEvictionPolicy:缓存清空策略
1.FIFO:first in first out 先讲先出
2.LFU: Less Frequently Used 一直以来最少被使用的
3.LRU:Least Recently Used 最近最少使用的
另外,需要说明下面几个:
1) diskStore:如果缓存超出配置规定的大小,就会存在磁盘哪个位置
2) defaultCache:这个是强制配置项,如果某些对象没有配置缓存策略,那么默认就是使用这个default配置
3) cache name=”news”:为News类配置的缓存策略
4)
说明:
1) hibernate.cache.region.factory_class是hibernate配置二级缓存的工厂类,这里我们使
3) hibernate.cache.use_second_level_cache的只是boolean,表示是否开启二级缓存
4) hibernate.cache.use_query_cache表示是否开启查询缓存,如果不开启,那么HQL的查询结果将不会被缓存
5) net.sf.ehcache.configurationResourceName配置ehcache的配置文件位置,如果不配置,ehcache会默认认为classpath下 的ehcache.xml文件
上面关闭了二级缓存,运行测试类,控制打印:
一级缓存不存在news时,每查询一次news对象就执行依次sql
控制台打印:
可以看到,当我们在清除一级缓存的时候,再次查询同样的对象,hibernate不会再次执行sql,而是从二级缓存里去读取
get:先从一级缓存中查询符合条件的对象,找不到则直接从数据库中查询,如果都查询不到则返回null;
load:先从一级缓存中查询符合条件的对象,找不到再在二级缓存中查询,如果还找不到就抛出异常;
1.项目目录结构
2.项目依赖
下面是pom.xml文件[code=language-xml]<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>HibernateEHCacheSample</groupId> <artifactId>HibernateEHCacheSample</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>war</packaging> <name>HibernateEHCacheSample</name> <description /> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- Hibernate Core API --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>4.3.5.Final</version> </dependency> <!-- MySQL Driver --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.0.5</version> </dependency> <!-- EHCache Core APIs --> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.6.9</version> </dependency> <!-- Hibernate EHCache API --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>4.3.5.Final</version> </dependency> <!-- EHCache uses slf4j for logging --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.5</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>2.3.2</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>2.2</version> <configuration> <version>3.0</version> <failOnMissingWebXml>false</failOnMissingWebXml> </configuration> </plugin> </plugins> </build> </project>
3.配置缓存策略
3.1 Model类
这个实例中对这个类做缓存[code=language-java]package com.lin.hibernate.model; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity @Table(name="TB_NEWS") @Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region="news") public class News { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "NEWS_ID") private int id; @Column(name="TITLE") private String title; @Column(name="CONTENT") private String content; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; } @Override public String toString() { return "News [id=" + id + ", title=" + title + ", content=" + content + "]"; } }
3.2 EHCache配置文件
[code=language-xml]<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true"> <diskStore path="java.io.tmpdir/ehcache" /> <defaultCache maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" diskSpoolBufferSizeMB="30" maxEntriesLocalDisk="10000000" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" statistics="true"> <persistence strategy="localTempSwap" /> </defaultCache> <cache name="news" maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="5" timeToLiveSeconds="10"> <persistence strategy="localTempSwap" /> </cache> <cache name="org.hibernate.cache.internal.StandardQueryCache" maxEntriesLocalHeap="5" eternal="false" timeToLiveSeconds="120"> <persistence strategy="localTempSwap" /> </cache> <cache name="org.hibernate.cache.spi.UpdateTimestampsCache" maxEntriesLocalHeap="5000" eternal="true"> <persistence strategy="localTempSwap" /> </cache> </ehcache>
说明一下上面的一些配置项:
name:cache唯一标识
eternal:缓存是否永久有效
maxElementsInMemory:内存中最大缓存对象数
overflowToDisk(true,false):缓存对象达到最大数后,将缓存写到硬盘中
diskPersistent:硬盘持久化
timeToIdleSeconds:缓存清除时间
timeToLiveSeconds:缓存存活时间
memoryStoreEvictionPolicy:缓存清空策略
1.FIFO:first in first out 先讲先出
2.LFU: Less Frequently Used 一直以来最少被使用的
3.LRU:Least Recently Used 最近最少使用的
另外,需要说明下面几个:
1) diskStore:如果缓存超出配置规定的大小,就会存在磁盘哪个位置
2) defaultCache:这个是强制配置项,如果某些对象没有配置缓存策略,那么默认就是使用这个default配置
3) cache name=”news”:为News类配置的缓存策略
4)
配置org.hibernate.cache.internal.StandardQueryCache 和 org.hibernate.cache.spi.UpdateTimestampsCache,不然ehcache会有一些警告
4.Hibernate
4.1 hibernate.cfg.xml
[code=language-xml]<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration SYSTEM "classpath://org/hibernate/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.password">root</property> <property name="hibernate.connection.url">jdbc:mysql://localhost/test</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <property name="hibernate.current_session_context_class">thread</property> <property name="hibernate.show_sql">true</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property> <!-- For singleton factory --> <!-- <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</property> --> <!-- enable second level cache and query cache --> <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.use_query_cache">true</property> <property name="net.sf.ehcache.configurationResourceName">/ehcache.xml</property> <mapping class="com.lin.hibernate.model.News" /> </session-factory> </hibernate-configuration>
说明:
1) hibernate.cache.region.factory_class是hibernate配置二级缓存的工厂类,这里我们使
org.hibernate.cache.ehcache.EhCacheRegionFactory
如果想使用单例工厂,那么就用org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
2) 如果使用的是Hibernate3,那么上面对应的两个类就应该是 net.sf.ehcache.hibernate.EhCacheRegionFactory和
net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory
3) hibernate.cache.use_second_level_cache的只是boolean,表示是否开启二级缓存
4) hibernate.cache.use_query_cache表示是否开启查询缓存,如果不开启,那么HQL的查询结果将不会被缓存
5) net.sf.ehcache.configurationResourceName配置ehcache的配置文件位置,如果不配置,ehcache会默认认为classpath下 的ehcache.xml文件
4.2 HibernateUtil
[code=language-java]package com.lin.hibernate.util; import org.hibernate.SessionFactory; import org.hibernate.boot.registry.StandardServiceRegistryBuilder; import org.hibernate.cfg.Configuration; import org.hibernate.service.ServiceRegistry; public class HibernateUtil { private static SessionFactory sessionFactory; private static SessionFactory buildSessionFactory() { try { // Create the SessionFactory from hibernate.cfg.xml Configuration configuration = new Configuration(); configuration.configure("hibernate.cfg.xml"); System.out.println("Hibernate Configuration loaded"); ServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties()).build(); System.out.println("Hibernate serviceRegistry created"); SessionFactory sessionFactory = configuration.buildSessionFactory(serviceRegistry); return sessionFactory; } catch (Throwable ex) { System.err.println("Initial SessionFactory creation failed." + ex); ex.printStackTrace(); throw new ExceptionInInitializerError(ex); } } public static SessionFactory getSessionFactory() { if(sessionFactory == null) sessionFactory = buildSessionFactory(); return sessionFactory; } }
5. 怎么知道二级缓存发挥了作用?
5.1 测试类
[code=language-java]package com.lin.hibernate.main; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import com.lin.hibernate.model.News; import com.lin.hibernate.util.HibernateUtil; public class HibernateEHCacheMain { public static void main(String[] args) { System.out.println("Temp Dir:"+System.getProperty("java.io.tmpdir")); //Initialize Sessions SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); // News news = new News(); // news.setTitle("Test EHcache"); // news.setContent("This is a news..."); // session.save(news); News news = (News)session.get(News.class, 1); System.out.println(news.toString()); session.evict(news);//清除了一级缓存 news = (News)session.get(News.class, 1); System.out.println(news.toString()); //Release resources transaction.commit(); sessionFactory.close(); } }
5.2 没有二级缓存是怎么样
首先看没有二级缓存的情况,在hibernate.cfg.xml里面配置:[code=language-xml]<!-- enable second level cache and query cache --> <property name="hibernate.cache.use_second_level_cache">false</property> <property name="hibernate.cache.use_query_cache">false</property>
上面关闭了二级缓存,运行测试类,控制打印:
一级缓存不存在news时,每查询一次news对象就执行依次sql
5.3 开启二级缓存
在hibernate.cfg.xml里面设置[code=language-xml]<!-- enable second level cache and query cache --> <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.use_query_cache">true</property>
控制台打印:
可以看到,当我们在清除一级缓存的时候,再次查询同样的对象,hibernate不会再次执行sql,而是从二级缓存里去读取
5.4 关于load和get
有时,配置了二级缓存却发现没有作用,应该看看使用的查询接口是load还是getget:先从一级缓存中查询符合条件的对象,找不到则直接从数据库中查询,如果都查询不到则返回null;
load:先从一级缓存中查询符合条件的对象,找不到再在二级缓存中查询,如果还找不到就抛出异常;
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- c++11 + SDL2 + ffmpeg +OpenAL + java = Android播放器
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树