1、二級(jí)緩存的知識(shí)
創(chuàng)新互聯(lián)主營(yíng)津南網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司,主營(yíng)網(wǎng)站建設(shè)方案,app開發(fā)定制,津南h5重慶小程序開發(fā)搭建,津南網(wǎng)站營(yíng)銷推廣歡迎津南等地區(qū)企業(yè)咨詢
Hibernate提供的緩存:有一級(jí)緩存、二級(jí)緩存。 目的是為了減少對(duì)數(shù)據(jù)庫(kù)的訪問次數(shù),提升程序執(zhí)行效率!
一級(jí)緩存:基于Session的緩存,緩存內(nèi)容只在當(dāng)前session有效,session關(guān)閉,緩存內(nèi)容失效!
特點(diǎn):作用范圍較??! 緩存的時(shí)間短。緩存效果不明顯。
二級(jí)緩存:
Hibernate提供了基于應(yīng)用程序級(jí)別的緩存, 可以跨多個(gè)session,即不同的session都可以訪問緩存數(shù)據(jù)。 這個(gè)緩存也叫二級(jí)緩存。
Hibernate提供的二級(jí)緩存有默認(rèn)的實(shí)現(xiàn),且是一種可插配的緩存框架!如果用戶想用二級(jí)緩存,只需要在hibernate.cfg.xml中配置即可;不想用,直接移除,不影響代碼。
如果用戶覺得hibernate提供的框架不好用,可以換其他的緩存框架或自己實(shí)現(xiàn)緩存框架都可以。
下面的配置位于%hibernate%/project/etc/hibernate.properties中
########################## ### Second-level Cache ### ########################## ## disable the second-level cache 二級(jí)緩存默認(rèn)不開啟,需要手動(dòng)開啟 #hibernate.cache.use_second_level_cache false ## enable the query cache #hibernate.cache.use_query_cache true 開啟查詢緩存 ## choose a cache implementation 二級(jí)緩存框架的實(shí)現(xiàn) #hibernate.cache.provider_class org.hibernate.cache.EhCacheProvider #hibernate.cache.provider_class org.hibernate.cache.EmptyCacheProvider hibernate.cache.provider_class org.hibernate.cache.HashtableCacheProvider #hibernate.cache.provider_class org.hibernate.cache.TreeCacheProvider #hibernate.cache.provider_class org.hibernate.cache.OSCacheProvider #hibernate.cache.provider_class org.hibernate.cache.SwarmCacheProvider
緩存的并發(fā)策略
<class-cache usage="read-only"/> 放入二級(jí)緩存的對(duì)象,只讀; <class-cache usage="nonstrict-read-write"/> 非嚴(yán)格的讀寫 <class-cache usage="read-write"/> 讀寫; 放入二級(jí)緩存的對(duì)象可以讀、寫; <class-cache usage="transactional"/> (基于事務(wù)的策略)
2、使用二級(jí)緩存
二級(jí)緩存,使用步驟
1)開啟二級(jí)緩存
<property name="hibernate.cache.use_second_level_cache">true</property>
2)指定緩存框架
<property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>
3)指定那些類加入二級(jí)緩存
<!-- 指定哪一些類,需要加入二級(jí)緩存 --> <class-cache usage="read-write" class="com.rk.hibernate.cache.Department"/> <class-cache usage="read-write" class="com.rk.hibernate.cache.Employee"/> <!-- 集合緩存[集合緩存的元素對(duì)象,也加加入二級(jí)緩存] --> <collection-cache usage="read-write" collection="com.rk.hibernate.cache.Department.emps"/>
4)測(cè)試二級(jí)緩存!
示例代碼和配置
hibernate.cfg.xml
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <!-- 通常,一個(gè)session-factory節(jié)點(diǎn)代表一個(gè)數(shù)據(jù)庫(kù) --> <session-factory> <!-- 1. 數(shù)據(jù)庫(kù)連接配置 --> <property name="hibernate.connection.driver_class">com.MySQL.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql:///test</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">root</property> <!-- 數(shù)據(jù)庫(kù)方言配置, hibernate在運(yùn)行的時(shí)候,會(huì)根據(jù)不同的方言生成符合當(dāng)前數(shù)據(jù)庫(kù)語(yǔ)法的sql --> <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property> <!-- 2. 其他相關(guān)配置 --> <!-- 2.1 顯示hibernate在運(yùn)行時(shí)候執(zhí)行的sql語(yǔ)句 --> <property name="hibernate.show_sql">true</property> <!-- 2.2 格式化sql --> <property name="hibernate.format_sql">false</property> <!-- 2.3 自動(dòng)建表 --> <property name="hibernate.hbm2ddl.auto">update</property> <!--****************** 【二級(jí)緩存配置】****************** --> <!-- a. 開啟二級(jí)緩存 --> <property name="hibernate.cache.use_second_level_cache">true</property> <!-- b. 指定使用哪一個(gè)緩存框架(默認(rèn)提供的) --> <property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property> <!-- 開啟查詢緩存 --> <property name="hibernate.cache.use_query_cache">true</property> <!-- c. 指定哪一些類,需要加入二級(jí)緩存 --> <class-cache usage="read-write" class="com.rk.hibernate.cache.Department"/> <class-cache usage="read-write" class="com.rk.hibernate.cache.Employee"/> <!-- 集合緩存[集合緩存的元素對(duì)象,也加加入二級(jí)緩存] --> <collection-cache usage="read-write" collection="com.rk.hibernate.cache.Department.emps"/> </session-factory> </hibernate-configuration>
Department.java
package com.rk.hibernate.cache; import java.util.Set; public class Department { private int deptId; private String deptName; private Set<Employee> emps; private int version; public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } public int getDeptId() { return deptId; } public void setDeptId(int deptId) { this.deptId = deptId; } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } public Set<Employee> getEmps() { return emps; } public void setEmps(Set<Employee> emps) { this.emps = emps; } @Override public String toString() { return "Department [deptId=" + deptId + ", deptName=" + deptName + "]"; } }
Department.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.rk.hibernate.cache" auto-import="true"> <class name="Department" table="T_Department"> <!-- <cache usage="read-only"/> --> <id name="deptId" column="id"> <generator class="native"></generator> </id> <version name="version" column="dept_version"></version> <property name="deptName" column="name" type="string"></property> <set name="emps" table="T_Employee"> <!-- <cache usage="read-only"/> --> <key column="deptId"></key> <one-to-many class="Employee"/> </set> </class> </hibernate-mapping>
Employee.java
package com.rk.hibernate.cache; public class Employee { private int empId; private String empName; private int salary; private Department dept; private int version; public int getVersion() { return version; } public void setVersion(int version) { this.version = version; } public int getEmpId() { return empId; } public void setEmpId(int empId) { this.empId = empId; } public String getEmpName() { return empName; } public void setEmpName(String empName) { this.empName = empName; } public int getSalary() { return salary; } public void setSalary(int salary) { this.salary = salary; } public Department getDept() { return dept; } public void setDept(Department dept) { this.dept = dept; } @Override public String toString() { return "Employee [empId=" + empId + ", empName=" + empName + ", salary=" + salary + "]"; } }
Employee.hbm.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping package="com.rk.hibernate.cache" auto-import="true"> <class name="Employee" table="T_Employee"> <!-- <cache usage="read-only"/> --> <id name="empId" column="id"> <generator class="native"></generator> </id> <version name="version" column="emp_version"></version> <property name="empName" column="name" type="string"></property> <property name="salary" column="salary" type="int"></property> <many-to-one name="dept" column="deptId" class="Department"></many-to-one> </class> </hibernate-mapping>
App.java
package com.rk.hibernate.cache; import java.util.Iterator; import java.util.List; import java.util.Set; import org.hibernate.Query; import org.hibernate.SQLQuery; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; import org.junit.Test; public class App { private static SessionFactory sf; static { sf = new Configuration() .configure() .addClass(Department.class) .addClass(Employee.class) .buildSessionFactory(); } // 1. 測(cè)試二級(jí)緩存的使用 //思路:sesion本身提供了一級(jí)緩存,它是mandatory,不能關(guān)閉 //二級(jí)緩存,是optional,通過配置文件可以開啟,可以關(guān)閉。 //如果不開啟二級(jí)緩存,兩個(gè)session查詢同一個(gè)id的數(shù)據(jù),會(huì)發(fā)送兩個(gè)SQL語(yǔ)句 //如果開啟二級(jí)緩存,兩個(gè)session查詢同一個(gè)id的數(shù)據(jù),會(huì)發(fā)送一條SQL語(yǔ)句 //通過開啟和關(guān)閉二級(jí)緩存,來查看執(zhí)行的SQL數(shù)目 @Test public void testSecondLevelCache() { //第1次查詢,第一個(gè)session Session session1 = sf.openSession(); session1.beginTransaction(); Department dept1 = (Department) session1.get(Department.class, 3); Set<Employee> emps1 = dept1.getEmps(); System.out.println(dept1); System.out.println(emps1); session1.getTransaction().commit(); session1.close(); System.out.println("-------------------------------"); //第2次查詢,第二個(gè)session Session session2 = sf.openSession(); session2.beginTransaction(); Department dept2 = (Department) session2.get(Department.class, 3); Set<Employee> emps2 = dept2.getEmps(); System.out.println(dept2); System.out.println(emps2); session2.getTransaction().commit(); session2.close(); } @Test public void testQueryCache() { // 第1次查詢,第一個(gè)session Session session1 = sf.openSession(); session1.beginTransaction(); // HQL查詢 【setCacheable 指定從二級(jí)緩存找,或者是放入二級(jí)緩存】 Query q1 = session1.createQuery("from Department").setCacheable(true); List<Department> list1 = q1.list(); System.out.println(list1); session1.getTransaction().commit(); session1.close(); System.out.println("-------------------------------"); // 第2次查詢,第二個(gè)session Session session2 = sf.openSession(); session2.beginTransaction(); // HQL查詢 【setCacheable 指定從二級(jí)緩存找,或者是放入二級(jí)緩存】 Query q2 = session2.createQuery("from Department").setCacheable(true); List<Department> list2 = q2.list(); System.out.println(list2); session2.getTransaction().commit(); session2.close(); } }
當(dāng)我們開啟二級(jí)緩存后,例如在上面的testSecondLevelCache()方法中,第一次從Session讀取數(shù)據(jù)后,會(huì)存儲(chǔ)在二級(jí)緩存上;第二次打開Session,程序再進(jìn)行相同查詢,就不需要再發(fā)送SQL語(yǔ)句,因?yàn)樗鼤?huì)從二級(jí)緩存中讀取數(shù)據(jù)。
有一點(diǎn)需要注意:如果二級(jí)緩存中沒有數(shù)據(jù),第一次開啟Session讀取數(shù)據(jù),并調(diào)用session.clear()方法,再讀取數(shù)據(jù),會(huì)發(fā)送兩次SQL語(yǔ)句。
@Test public void test1() { // 第1次查詢,第一個(gè)session Session session1 = sf.openSession(); session1.beginTransaction(); Department dept1 = (Department) session1.get(Department.class, 2); System.out.println(dept1); System.out.println(dept1.getEmps()); session1.clear(); dept1 = (Department) session1.get(Department.class, 2); System.out.println(dept1); System.out.println(dept1.getEmps()); session1.getTransaction().commit(); session1.close(); }
結(jié)果如下:
Hibernate: select department0_.id as id0_0_, department0_.dept_version as dept2_0_0_, department0_.name as name0_0_ from T_Department department0_ where department0_.id=? Department [deptId=2, deptName=woqu] Hibernate: select emps0_.deptId as deptId0_1_, emps0_.id as id1_, emps0_.id as id1_0_, emps0_.emp_version as emp2_1_0_, emps0_.name as name1_0_, emps0_.salary as salary1_0_, emps0_.deptId as deptId1_0_ from T_Employee emps0_ where emps0_.deptId=? [Employee [empId=3, empName=TO_T_, salary=4]] Hibernate: select department0_.id as id0_0_, department0_.dept_version as dept2_0_0_, department0_.name as name0_0_ from T_Department department0_ where department0_.id=? Department [deptId=2, deptName=woqu] Hibernate: select emps0_.deptId as deptId0_1_, emps0_.id as id1_, emps0_.id as id1_0_, emps0_.emp_version as emp2_1_0_, emps0_.name as name1_0_, emps0_.salary as salary1_0_, emps0_.deptId as deptId1_0_ from T_Employee emps0_ where emps0_.deptId=? [Employee [empId=3, empName=TO_T_, salary=4]]
如果二級(jí)緩存中已經(jīng)存在數(shù)據(jù),第二次開啟Session,調(diào)用session.clear(),再讀取數(shù)據(jù),并不會(huì)發(fā)送SQL語(yǔ)句。
@Test public void test1() { Session session2 = sf.openSession(); session2.beginTransaction(); Department dept2 = (Department) session2.get(Department.class, 2); System.out.println(dept2); System.out.println(dept2.getEmps()); session2.getTransaction().commit(); session2.close(); System.out.println("-------------------------------"); // 第1次查詢,第一個(gè)session Session session1 = sf.openSession(); session1.beginTransaction(); Department dept1 = (Department) session1.get(Department.class, 2); System.out.println(dept1); System.out.println(dept1.getEmps()); session1.clear(); dept1 = (Department) session1.get(Department.class, 2); System.out.println(dept1); System.out.println(dept1.getEmps()); session1.getTransaction().commit(); session1.close(); System.out.println("-------------------------------"); }
結(jié)果如下:
Hibernate: select department0_.id as id0_0_, department0_.dept_version as dept2_0_0_, department0_.name as name0_0_ from T_Department department0_ where department0_.id=? Department [deptId=2, deptName=woqu] Hibernate: select emps0_.deptId as deptId0_1_, emps0_.id as id1_, emps0_.id as id1_0_, emps0_.emp_version as emp2_1_0_, emps0_.name as name1_0_, emps0_.salary as salary1_0_, emps0_.deptId as deptId1_0_ from T_Employee emps0_ where emps0_.deptId=? [Employee [empId=3, empName=TO_T_, salary=4]] ------------------------------- Department [deptId=2, deptName=woqu] [Employee [empId=3, empName=TO_T_, salary=4]] Department [deptId=2, deptName=woqu] [Employee [empId=3, empName=TO_T_, salary=4]] -------------------------------
當(dāng)前名稱:(20)Hibernate二級(jí)緩存
轉(zhuǎn)載來于:http://aaarwkj.com/article46/pcsohg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站制作、微信小程序、外貿(mào)網(wǎng)站建設(shè)、商城網(wǎng)站、網(wǎng)頁(yè)設(shè)計(jì)公司、域名注冊(cè)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)