Hibernate二级缓存 使用 所有会话工厂的会话对象的公共缓存。当你有多个会话对象来自同一个会话工厂时,它非常有用。

SessionFactory 持有二级缓存数据。它对所有会话对象是全局的,并且默认未启用。

不同的供应商提供了二级缓存的实现:

  1. EH Cache
  2. OS Cache
  3. Swarm Cache
  4. JBoss Cache

每种实现提供了不同的缓存使用功能。二级缓存有四种使用方式:

  1. read-only: 缓存仅用于读取操作。
  2. nonstrict-read-write: 缓存可用于读取和写入,但一次只能执行一个操作。
  3. read-write: 缓存可用于读取和写入,可以同时使用。
  4. transactional: 缓存用于事务。

在hbm.xml文件中,可以将缓存使用属性应用于类或集合级别。定义缓存使用的示例如下:

<cache usage="read-only" />

下面展示了二级缓存实现及缓存使用的情况:

实现read-onlynonstrict-read-writeread-writetransactional
EH CacheYesYesYesNo
OS CacheYesYesYesNo
Swarm CacheYesYesNoNo
JBoss CacheNoNoNoYes

Hibernate二级缓存示例

要通过示例理解二级缓存,我们需要遵循以下步骤:

  1. 使用Maven创建持久类
  2. 在pom.xml文件中添加项目信息和配置
  3. 创建配置文件
  4. 创建检索持久对象的类

假设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();  
  }  
}  

输出:

6-1.jpg

如我们所见,Hibernate没有执行两次查询。如果你不使用二级缓存,Hibernate将执行两次查询,因为这两个查询使用了不同的Session对象。通过启用二级缓存,多个会话对象可以共享缓存数据,从而提高应用程序的性能。

标签: Hibernate, Hibernate教程, Hibernate框架, Hibernate框架设计, Hibernate初级教程, Hibernate框架用法, Hibernate指南, Hibernate入门, Hibernate中级教程, Hibernate进阶教程, Hibernate高级教程, Hibernate下载