1, level two cache knowledge
Hibernate provides cache: one-level cache , level two cache . The goal is to reduce the number of access to the database, improve program execution efficiency!
First- level cache : Session-based cache, cached content only valid in the current session, session closed, cache content Invalid!
Features: small range of Functions! Cache time is short. The cache effect is not obvious.
level Two cache :
Hibernate provides application-level caching that can access cached data across multiple sessions, that is, different sessions of the session. This cache is also called a level two cache.
Hibernate provides a two level cache with a default implementation and is a pluggable caching framework! If the user wants to use level two cache, only need to configure in Hibernate.cfg.xml, do not want to use, directly remove, do not affect the code.
If the user feels that Hibernate provides a framework that is not good enough, you can switch to another cache framework or implement your own caching framework.
The following configuration is in%hibernate%/project/etc/hibernate.properties
############################# Second-level Cache ############################### Disable the second-level cache Secondary cache does not turn on by default and requires manual #hibernate.cache.use_second_level_cache false## enable the query Cache#hibernate.cache.use_query_ Cache true Open Query Cache # # Choose a cache implementation level two caching framework implementation #hibernate.cache.provider_class Org.hibernate.cache.ehcacheprovider#hibernate.cache.provider_class Org.hibernate.cache.EmptyCacheProviderhibernate.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
Concurrency Policy for caching
<class-cache usage= "Read-only"/> into a Level two cache object, read-only; <class-cache usage= "Nonstrict-read-write"/> Non-strict read-write <class-cache usage= "Read-write"/> Read and write; the objects that are placed in level two cache can be read and written; <class-cache usage= "Transactional"/> (transaction-based policy)
2. Use level Two cache
Second-level caching, using steps
1) Turn on level two cache
<property name= "Hibernate.cache.use_second_level_cache" >true</property>
2) Specify the caching framework
<property name= "Hibernate.cache.provider_class" >org.hibernate.cache.hashtablecacheprovider</property >
3) Specify those classes to join level two cache
<!--specify which classes need to be added to level two cache--><class-cache usage= "Read-write" class= "Com.rk.hibernate.cache.Department"/> <class-cache usage= "Read-write" class= "Com.rk.hibernate.cache.Employee"/><!--collection Cache [Element object of the collection cache, also added to level two cache]-- ><collection-cache usage= "Read-write" collection= "Com.rk.hibernate.cache.Department.emps"/>
4) Test level two cache!
Sample code and Configuration
Hibernate.cfg.xml
<! doctype hibernate-configuration public "-//Hibernate/ hibernate configuration dtd 3.0//en " "/http Www.hibernate.org/dtd/hibernate-configuration-3.0.dtd "> 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;} @Overridepublic 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 "> 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;} @Overridepublic 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 ">
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. test the use of level two cache//ideas: Sesion itself provides a first-level cache, it is mandatory, can not be closed///two-level cache, is optional, through the configuration file can be turned on, can be closed. If you do not turn on level two cache, two sessions query the same ID data, will send two SQL statements//If you turn on the two level cache, two sessions query the same ID data, will send an SQL statement//by turning on and off the level two cache, To see the number of SQL executed @testpublic void testsecondlevelcache () {//1th query, First sessionsession session1 = sf.opensession (); Session1.begintransaction ();D epartment dept1 = (Department) Session1.get (department.class, 3); Set<employee&gT; emps1 = dept1.getemps (); System.out.println (DEPT1); System.out.println (EMPS1); Session1.gettransaction (). commit (); Session1.close (); System.out.println ("-------------------------------");//2nd query, second sessionsession session2 = Sf.opensession (); Session2.begintransaction ();D epartment dept2 = (Department) session2.get ( DEPARTMENT.CLASS,&NBSP;3); Set<employee> emps2 = dept2.getemps (); System.out.println (DEPT2); System.out.println (EMPS2); Session2.gettransaction (). commit (); Session2.close ();} @Testpublic void testquerycache () {// 1th time, first sessionsession session1 = Sf.opensession (); Session1.begintransaction ();// hql query setcacheable specified from level two cache, Or put in a level two cache "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 ("-------------------------------");// 2nd query, second sessionsession session2 = Sf.opensession (); Session2.begintransaction ();// hql query setcacheable specified from level two cache, Or put in a level two cache "Query q2 = session2.createquery (" From department "). Setcacheable (True); List<department> list2 = q2.list (); System.out.println (List2); Session2.gettransaction (). commit (); Session2.close ();}}
When we turn on the level two cache, for example in the above Testsecondlevelcache () method, the first time the data is read from the session, it will be stored in the level two cache; The second time the session is opened, the same query will not need to send the SQL statement. Because it reads the data from the level two cache.
One thing to note : If there is no data in the level two cache, the first time the session is opened to read the data, and the Session.clear () method is called and then the data is read, the SQL statement is sent two times .
@Testpublic void Test1 () {//1th query, first sessionsession Session1 = Sf.opensession (); Session1.begintransaction ();D Epartment dept1 = (Department) session1.get (Department.class, 2); System.out.println (DEPT1); System.out.println (Dept1.getemps ()), Session1.clear ();d ept1 = (Department) session1.get (Department.class, 2); System.out.println (DEPT1); System.out.println (Dept1.getemps ()); Session1.gettransaction (). commit (); Session1.close ();}
The results are as follows:
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]]
If data already exists in the level two cache, the session is opened for the second time, Session.clear () is called, and the data is read, and the SQL statement is not sent.
@Testpublic void Test1 () {Session session2 = sf.opensession (); Session2.begintransaction ();D epartment dept2 = ( Department) Session2.get (Department.class, 2); System.out.println (DEPT2); System.out.println (Dept2.getemps ()); Session2.gettransaction (). commit (); Session2.close (); System.out.println ("-------------------------------");//1th query, first sessionsession Session1 = Sf.opensession (); Session1.begintransaction ();D epartment dept1 = (Department) session1.get (Department.class, 2); System.out.println (DEPT1); System.out.println (Dept1.getemps ()), Session1.clear ();d ept1 = (Department) session1.get (Department.class, 2); System.out.println (DEPT1); System.out.println (Dept1.getemps ()); Session1.gettransaction (). commit (); Session1.close (); System.out.println ("-------------------------------");}
The results are as follows:
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,&NBSP;DEPTNAME=WOQU][EMPLOYEE&NBSP;[EMPID=3,&NBSP;EMPNAME=TO_T_,&NBSP;SALARY=4]]--------------------- ----------
() Hibernate level two cache