Hibernate第二级缓存是会话工厂的所有会话(Session)对象所使用的公共缓存。 如果您有来自会话工厂的多个会话(Session)对象,就可以操作会话工厂中的第二级缓存的数据。
SessionFactory
类用于保存二级缓存数据。 它是所有会话对象的全局,默认情况下是不启用的。
不同厂商提供了二级缓存的实现。
- EH二级缓存
- OS二级缓存
- Swarm二级缓存
- JBoss二级缓存
每个实现提供不同的缓存使用功能。 有四种方法可以使用二级缓存。
- 只读:缓存将适用于只读操作。
- 非严格读写:缓存可用于读写,但一次只能读写。
- 读写:缓存将用于读写,可以同时使用。
- 事务处理:缓存将用于事务处理。
缓存使用属性可以应用于hbm.xml
文件中的类或集合级别。 下面给出了定义缓存使用情况的例子:
下面来看看看二级缓存实现和缓存使用情况。<cache usage="read-only" />
实现 | 只读 | 非限制读写 | 读写 | 操作 |
---|---|---|---|---|
EH二级缓存 | Yes | Yes | Yes | No |
OS二级缓存 | Yes | Yes | Yes | No |
Swarm二级缓存 | Yes | Yes | No | No |
JBoss二级缓存 | No | No | No | Yes |
使用EH缓存的二级缓存示例的额外步骤
1)在hibernate.cfg.xml
文件中添加2
个配置设置
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
2) 在hbm
文件中添加缓存使用情况设置
<cache usage="read-only" />
3) 创建ehcache.xml
文件
<?xml version="1.0"?>
<ehcache>
<defaultCache maxElementsInMemory="100" eternal="true"/>
</ehcache>
Hibernate二级缓存示例
要通过下面示例了解二级缓存,我们需要创建一个Java项目:secondlevel
, 其完整的目录结构如下所示 -
创建以下页面:
- Employee.java
- employee.hbm.xml
- hibernate.cfg.xml
- ehcache.xml
- MainTest.java
注意:在这里,我们假设,在MySQL数据库中有一个
emp_cache2
表并包含一些记录。
文件: Employee.java
package com.yiibai;
public class Employee {
private int id;
private String name;
private float salary;
public Employee() {
super();
}
public Employee(String name, float salary) {
super();
this.name = name;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getSalary() {
return salary;
}
public void setSalary(float salary) {
this.salary = salary;
}
}
文件: employee.hbm.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.yiibai.Employee" table="emp_cache">
<cache usage="read-only" />
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<property name="salary"></property>
</class>
</hibernate-mapping>
在这里,我们使用只读(read-only)高速缓存来使用该类。缓存使用情况也可用于集合。
文件: hibernate.cfg.xml
要实现二级缓存,我们需要在配置文件中定义cache.provider_class
属性。
文件:ehcache.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="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>
<cache name="com.yiibai.Employee" maxElementsInMemory="100"
eternal="false" timeToIdleSeconds="5" timeToLiveSeconds="200" />
</ehcache>
我们需要创建ehcache.xml
文件来定义缓存属性。
defaultCache
将用于所有持久化类。 我们还可以通过使用 cache
元素来明确定义持久化类。eternal
如果我们指定eternal =“true”
,则不需要定义timeToIdleSeconds
和timeToLiveSeconds
属性,因为它将由hibernate
内部处理。 指定eternal =“false”
给程序员控制,但是我们需要定义timeToIdleSeconds
和timeToLiveSeconds
属性timeToIdleSeconds
它定义了二级缓存中对象可以空闲多少秒。timeToLiveSeconds
它定义了在第二级缓存中对象可以存储多少秒,无论它是否空闲。
文件:MainTest.java
package com.yiibai;
import org.hibernate.*;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.*;
import org.hibernate.stat.Statistics;
public class MainTest {
public static void main(String[] args) {
// 在5.1.0版本汇总,hibernate则采用如下新方式获取:
// 1. 配置类型安全的准服务注册类,这是当前应用的单例对象,不作修改,所以声明为final
// 在configure("cfg/hibernate.cfg.xml")方法中,如果不指定资源路径,默认在类路径下寻找名为hibernate.cfg.xml的文件
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
.configure("hibernate.cfg.xml").build();
// 2. 根据服务注册类创建一个元数据资源集,同时构建元数据并生成应用一般唯一的的session工厂
SessionFactory sessionFactory = new MetadataSources(registry)
.buildMetadata().buildSessionFactory();
/**** 上面是配置准备,下面开始我们的数据库操作 ******/
Session session = sessionFactory.openSession();// 从会话工厂获取一个session
// creating transaction object
Transaction tx = session.beginTransaction();
Statistics stats = sessionFactory.getStatistics();
System.out.println("Stats enabled="+stats.isStatisticsEnabled());
stats.setStatisticsEnabled(true);
System.out.println("Stats enabled="+stats.isStatisticsEnabled());
session.save(new Employee("苏小牛", 12000));
session.save(new Employee("库日天", 19000));
Session session1 = sessionFactory.openSession();
Employee emp1 = (Employee) session1.load(Employee.class, 1);
System.out.println(emp1.getId() + " " + emp1.getName() + " "
+ emp1.getSalary());
session1.close();
//再次查询ID=1的员工信息,因为使用了缓存,这里不会再发出查询语句...
Session session11 = sessionFactory.openSession();
Employee emp11 = (Employee) session11.load(Employee.class, 1);
System.out.println(emp11.getId() + " " + emp11.getName() + " "
+ emp11.getSalary()