网站建设资讯

NEWS

网站建设资讯

(20)Hibernate二级缓存-创新互联

1、二级缓存的知识

专注于为中小企业提供网站建设、网站设计服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业鼓楼免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了成百上千家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。

Hibernate提供的缓存:有一级缓存二级缓存。 目的是为了减少对数据库的访问次数,提升程序执行效率!

一级缓存:基于Session的缓存,缓存内容只在当前session有效,session关闭,缓存内容失效!

特点:作用范围较小! 缓存的时间短。缓存效果不明显。

二级缓存

Hibernate提供了基于应用程序级别的缓存, 可以跨多个session,即不同的session都可以访问缓存数据。 这个缓存也叫二级缓存。

Hibernate提供的二级缓存有默认的实现,且是一种可插配的缓存框架!如果用户想用二级缓存,只需要在hibernate.cfg.xml中配置即可;不想用,直接移除,不影响代码。

如果用户觉得hibernate提供的框架不好用,可以换其他的缓存框架或自己实现缓存框架都可以。

下面的配置位于%hibernate%/project/etc/hibernate.properties中

########################## ### Second-level Cache ### ########################## ## disable the second-level cache 二级缓存默认不开启,需要手动开启 #hibernate.cache.use_second_level_cache false ## enable the query cache #hibernate.cache.use_query_cache true 开启查询缓存 ## choose a cache implementation 二级缓存框架的实现 #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

缓存的并发策略

     放入二级缓存的对象,只读;    非严格的读写     读写; 放入二级缓存的对象可以读、写;    (基于事务的策略)

2、使用二级缓存

二级缓存,使用步骤

    1)开启二级缓存

true

    2)指定缓存框架

org.hibernate.cache.HashtableCacheProvider

    3)指定那些类加入二级缓存

    4)测试二级缓存!

示例代码和配置

hibernate.cfg.xml

                           com.mysql.jdbc.Driver         jdbc:mysql:///test         root         root         org.hibernate.dialect.MySQL5Dialect                   true false update true org.hibernate.cache.HashtableCacheProvider true     

Department.java

package com.rk.hibernate.cache; import java.util.Set; public class Department { private int deptId; private String deptName; private Set 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 getEmps() { return emps; } public void setEmps(Set emps) { this.emps = emps; } @Override public String toString() { return "Department [deptId=" + deptId + ", deptName=" + deptName + "]"; } }

Department.hbm.xml

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

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. 测试二级缓存的使用 //思路:sesion本身提供了一级缓存,它是mandatory,不能关闭 //二级缓存,是optional,通过配置文件可以开启,可以关闭。 //如果不开启二级缓存,两个session查询同一个id的数据,会发送两个SQL语句 //如果开启二级缓存,两个session查询同一个id的数据,会发送一条SQL语句 //通过开启和关闭二级缓存,来查看执行的SQL数目 @Test public void testSecondLevelCache() { //第1次查询,第一个session Session session1 = sf.openSession(); session1.beginTransaction(); Department dept1 = (Department) session1.get(Department.class, 3); Set emps1 = dept1.getEmps(); System.out.println(dept1); System.out.println(emps1); session1.getTransaction().commit(); session1.close(); System.out.println("-------------------------------"); //第2次查询,第二个session Session session2 = sf.openSession(); session2.beginTransaction(); Department dept2 = (Department) session2.get(Department.class, 3); Set emps2 = dept2.getEmps(); System.out.println(dept2); System.out.println(emps2); session2.getTransaction().commit(); session2.close(); } @Test public void testQueryCache() { // 第1次查询,第一个session Session session1 = sf.openSession(); session1.beginTransaction(); // HQL查询  【setCacheable  指定从二级缓存找,或者是放入二级缓存】 Query q1 = session1.createQuery("from Department").setCacheable(true); List list1 = q1.list(); System.out.println(list1); session1.getTransaction().commit(); session1.close(); System.out.println("-------------------------------"); // 第2次查询,第二个session Session session2 = sf.openSession(); session2.beginTransaction(); // HQL查询  【setCacheable  指定从二级缓存找,或者是放入二级缓存】 Query q2 = session2.createQuery("from Department").setCacheable(true); List list2 = q2.list(); System.out.println(list2); session2.getTransaction().commit(); session2.close(); } }

当我们开启二级缓存后,例如在上面的testSecondLevelCache()方法中,第一次从Session读取数据后,会存储在二级缓存上;第二次打开Session,程序再进行相同查询,就不需要再发送SQL语句,因为它会从二级缓存中读取数据。

有一点需要注意如果二级缓存中没有数据,第一次开启Session读取数据,并调用session.clear()方法,再读取数据,会发送两次SQL语句

@Test public void test1() { // 第1次查询,第一个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(); }

结果如下:

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]]

如果二级缓存中已经存在数据,第二次开启Session,调用session.clear(),再读取数据,并不会发送SQL语句。

@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次查询,第一个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("-------------------------------"); }

结果如下:

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]] -------------------------------

另外有需要云服务器可以了解下创新互联cdcxhl.cn,海内外云服务器15元起步,三天无理由+7*72小时售后在线,公司持有idc许可证,提供“云服务器、裸金属服务器、高防服务器、香港服务器、美国服务器、虚拟主机、免备案服务器”等云主机租用服务以及企业上云的综合解决方案,具有“安全稳定、简单易用、服务可用性高、性价比高”等特点与优势,专为企业上云打造定制,能够满足用户丰富、多元化的应用场景需求。


文章题目:(20)Hibernate二级缓存-创新互联
浏览地址:http://cdweb.net/article/diphpi.html