Hibernate第二級快取是對談工廠的所有對談(Session)物件所使用的公共快取。 如果您有來自對談工廠的多個對談(Session)物件,就可以操作對談工廠中的第二級快取的資料。
SessionFactory
類用於儲存二級快取資料。 它是所有對談物件的全域性,預設情況下是不啟用的。
不同廠商提供了二級快取的實現。
每個實現提供不同的快取使用功能。 有四種方法可以使用二級快取。
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>
要通過下面範例了解二級快取,我們需要建立一個Java專案:secondlevel
, 其完整的目錄結構如下所示 -
建立以下頁面:
注意:在這裡,我們假設,在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());
session11.close();
Session session2 = sessionFactory.openSession();
Employee emp2 = (Employee) session2.load(Employee.class, 2);
System.out.println(emp2.getId() + " " + emp2.getName() + " "
+ emp2.getSalary());
session2.close();
tx.commit();
session.close();
sessionFactory.close();
}
}
我們可以看到,hibernate不會發出兩次查詢。 如果不使用二級快取,hibernate將會發出兩次查詢,因為這兩個查詢都使用不同的對談物件。
首先執行 MainTest.java
插入資料,然後再讀取資料。
執行 MainTest.java
得到以下結果,
log4j:WARN No appenders could be found for logger (org.jboss.logging).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
Wed Mar 29 21:38:06 CST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
Stats enabled=false
Stats enabled=true
Hibernate: insert into emp_cache (name, salary) values (?, ?)
Hibernate: insert into emp_cache (name, salary) values (?, ?)
Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_, employee0_.salary as salary3_0_0_ from emp_cache employee0_ where employee0_.id=?
Wed Mar 29 21:38:08 CST 2017 WARN: Establishing SSL connection without server's identity verification is not recommended. According to MySQL 5.5.45+, 5.6.26+ and 5.7.6+ requirements SSL connection must be established by default if explicit option isn't set. For compliance with existing applications not using SSL the verifyServerCertificate property is set to 'false'. You need either to explicitly disable SSL by setting useSSL=false, or set useSSL=true and provide truststore for server certificate verification.
1 蘇小牛 12000.0
1 蘇小牛 12000.0
Hibernate: select employee0_.id as id1_0_0_, employee0_.name as name2_0_0_, employee0_.salary as salary3_0_0_ from emp_cache employee0_ where employee0_.id=?
2 庫日天 19000.0