1.项目目录结构
2.项目依赖
下面是pom.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类
这个实例中对这个类做缓存
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配置文件
<?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
<?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.EhCacheRegionFactorynet.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
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 测试类
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里面配置:
<!-- 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里面设置
<!-- 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还是get
get:先从一级缓存中查询符合条件的对象,找不到则直接从数据库中查询,如果都查询不到则返回null;
load:先从一级缓存中查询符合条件的对象,找不到再在二级缓存中查询,如果还找不到就抛出异常;