Hibernate EHCache Second Level Cache Example

本文详细介绍了如何在Hibernate项目中集成EHCache实现二级缓存,包括Maven依赖配置、EHCache配置、Hibernate配置等关键步骤,并通过示例验证缓存的有效性。

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.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

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:先从一级缓存中查询符合条件的对象,找不到再在二级缓存中查询,如果还找不到就抛出异常;

转载于:https://my.oschina.net/ChiLin/blog/686928

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值