Hibernate教程-Hibernate 二级缓存
Hibernate二级缓存 使用 所有会话工厂的会话对象的公共缓存。当你有多个会话对象来自同一个会话工厂时,它非常有用。
SessionFactory 持有二级缓存数据。它对所有会话对象是全局的,并且默认未启用。
不同的供应商提供了二级缓存的实现:
- EH Cache
- OS Cache
- Swarm Cache
- JBoss Cache
每种实现提供了不同的缓存使用功能。二级缓存有四种使用方式:
- read-only: 缓存仅用于读取操作。
- nonstrict-read-write: 缓存可用于读取和写入,但一次只能执行一个操作。
- read-write: 缓存可用于读取和写入,可以同时使用。
- transactional: 缓存用于事务。
在hbm.xml文件中,可以将缓存使用属性应用于类或集合级别。定义缓存使用的示例如下:
<cache usage="read-only" />
下面展示了二级缓存实现及缓存使用的情况:
实现 | read-only | nonstrict-read-write | read-write | transactional |
---|---|---|---|---|
EH Cache | Yes | Yes | Yes | No |
OS Cache | Yes | Yes | Yes | No |
Swarm Cache | Yes | Yes | No | No |
JBoss Cache | No | No | No | Yes |
Hibernate二级缓存示例
要通过示例理解二级缓存,我们需要遵循以下步骤:
- 使用Maven创建持久类
- 在pom.xml文件中添加项目信息和配置
- 创建配置文件
- 创建检索持久对象的类
假设Oracle数据库中存在emp1012表并包含一些记录。
1) 使用Maven创建持久类
文件:Employee.java
package cn.javatiku;
import javax.persistence.*;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Table(name="emp1012")
@Cacheable
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
public class Employee {
@Id
private int id;
private String name;
private float salary;
public Employee() {}
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;
}
@Override
public String toString() {
return id + " " + name + " " + salary;
}
}
2) 在pom.xml文件中添加项目信息和配置
打开pom.xml文件并点击source。现在,在<dependencies>....</dependencies>标签之间添加以下依赖项。
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.16.Final</version>
</dependency>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc14</artifactId>
<version>10.2.0.4.0</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>2.10.3</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>5.2.16.Final</version>
</dependency>
3) 创建配置文件
文件:hibernate.cfg.xml
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 5.2.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-5.2.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<property name="dialect">org.hibernate.dialect.Oracle9Dialect</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:xe</property>
<property name="connection.username">system</property>
<property name="connection.password">jtp</property>
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="cache.use_second_level_cache">true</property>
<property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
<mapping class="cn.javatiku.Employee"/>
</session-factory>
</hibernate-configuration>
要实现二级缓存,我们需要在配置文件中定义 cache.provider_class 属性。
4) 创建检索持久对象的类
文件:FetchTest.java
package cn.javatiku;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
public class FetchTest {
public static void main(String[] args) {
StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build();
Metadata meta = new MetadataSources(ssr).getMetadataBuilder().build();
SessionFactory factory = meta.getSessionFactoryBuilder().build();
Session session1 = factory.openSession();
Employee emp1 = session1.load(Employee.class, 121);
System.out.println(emp1.getId() + " " + emp1.getName() + " " + emp1.getSalary());
session1.close();
Session session2 = factory.openSession();
Employee emp2 = session2.load(Employee.class, 121);
System.out.println(emp2.getId() + " " + emp2.getName() + " " + emp2.getSalary());
session2.close();
}
}
输出:
如我们所见,Hibernate没有执行两次查询。如果你不使用二级缓存,Hibernate将执行两次查询,因为这两个查询使用了不同的Session对象。通过启用二级缓存,多个会话对象可以共享缓存数据,从而提高应用程序的性能。