Hibernate 缓存--一级缓存

欢迎学习Hibernate缓存--第一级缓存示例教程。最近,我们学习了[HibernateHQL]、Hibernate architecture以及如何使用[HQL](/community/tutorials/hibernate-query-language-hql-example-tutorialHibernate Query Language(HQL)示例教程以面向对象的方式触发SQL查询。今天我们来看看Hibernate的一个重要方面--Hibernate缓存

Hibernate缓存

如果使用得当,hibernate休眠缓存中的休眠缓存、休眠缓存、一级缓存在获得快速应用程序性能方面非常有用。缓存背后的想法是减少数据库查询的数量,从而减少应用程序的吞吐时间。Hibernate提供了不同类型的缓存:

1.一级缓存 :Hibernate一级缓存与Session对象关联。默认情况下,Hibernate一级缓存处于启用状态,无法禁用它。然而,Hibernate提供了一些方法,通过这些方法,我们可以从缓存中删除选定的对象或完全清除缓存。会话中缓存的任何对象将对其他会话不可见,并且当会话关闭时,所有缓存的对象也将丢失。 2.二级缓存 :Hibernate二级缓存默认关闭,但我们可以通过配置开启。目前,EHCache和Infinisspan提供了Hibernate二级缓存的实现,我们可以使用它们。我们将在下一篇关于Hibernate缓存的教程中研究这一点。 3.查询缓存 :Hibernate还可以缓存查询的结果集。Hibernate查询缓存不缓存缓存中实际实体的状态;它只缓存值类型的标识符值和结果。因此,它应该始终与二级缓存一起使用。

Hibernate缓存--一级缓存示例

对于我的Hibernate一级缓存示例程序,我使用的配置与HQL Example中的配置相同,您可以签出并配置表,并使用伪数据填充它。让我们先来看看程序,它的输出,然后我们将介绍一些与Hibernate一级缓存相关的要点。HibernateCacheExample.java

 1package com.journaldev.hibernate.main;
 2
 3import org.hibernate.Session;
 4import org.hibernate.SessionFactory;
 5import org.hibernate.Transaction;
 6
 7import com.journaldev.hibernate.model.Employee;
 8import com.journaldev.hibernate.util.HibernateUtil;
 9
10public class HibernateCacheExample {
11
12    public static void main(String[] args) throws InterruptedException {
13    	
14    	SessionFactory sessionFactory = HibernateUtil.getSessionFactory();
15    	Session session = sessionFactory.getCurrentSession();
16    	Transaction tx = session.beginTransaction();
17    	
18    	//Get employee with id=1
19    	Employee emp = (Employee) session.load(Employee.class, new Long(1));
20    	printData(emp,1);
21    	
22    	//waiting for sometime to change the data in backend
23    	Thread.sleep(10000);
24    	
25    	//Fetch same data again, check logs that no query fired
26    	Employee emp1 = (Employee) session.load(Employee.class, new Long(1));
27    	printData(emp1,2);
28    	
29    	//Create new session
30    	Session newSession = sessionFactory.openSession();
31    	//Get employee with id=1, notice the logs for query
32    	Employee emp2 = (Employee) newSession.load(Employee.class, new Long(1));
33    	printData(emp2,3);
34    	
35    	//START: evict example to remove specific object from hibernate first level cache
36    	//Get employee with id=2, first time hence query in logs
37    	Employee emp3 = (Employee) session.load(Employee.class, new Long(2));
38    	printData(emp3,4);
39    	
40    	//evict the employee object with id=1
41    	session.evict(emp);
42    	System.out.println("Session Contains Employee with id=1?"+session.contains(emp));
43
44    	//since object is removed from first level cache, you will see query in logs
45    	Employee emp4 = (Employee) session.load(Employee.class, new Long(1));
46    	printData(emp4,5);
47    	
48    	//this object is still present, so you won't see query in logs
49    	Employee emp5 = (Employee) session.load(Employee.class, new Long(2));
50    	printData(emp5,6);
51    	//END: evict example
52    	
53    	//START: clear example to remove everything from first level cache
54    	session.clear();
55    	Employee emp6 = (Employee) session.load(Employee.class, new Long(1));
56    	printData(emp6,7);
57    	Employee emp7 = (Employee) session.load(Employee.class, new Long(2));
58    	printData(emp7,8);
59    	
60    	System.out.println("Session Contains Employee with id=2?"+session.contains(emp7));
61    	
62    	tx.commit();
63    	sessionFactory.close();
64    }
65
66    private static void printData(Employee emp, int count) {
67    	System.out.println(count+":: Name="+emp.getName()+", Zipcode="+emp.getAddress().getZipcode());
68    }
69
70}

当我们运行上面的示例时,输出包含大量与Hibernate相关的信息。但我们最感兴趣的是特定于代码的输出和Hibernate为加载数据而触发的查询。输出代码片段如下所示。

 1Hibernate Configuration loaded
 2Hibernate serviceRegistry created
 3Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
 41:: Name=Pankaj, Zipcode=95129
 52:: Name=Pankaj, Zipcode=95129
 6Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
 73:: Name=PankajK, Zipcode=95129
 8Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
 94:: Name=David, Zipcode=95051
10Session Contains Employee with id=1?false
11Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
125:: Name=Pankaj, Zipcode=95129
136:: Name=David, Zipcode=95051
14Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
157:: Name=Pankaj, Zipcode=95129
16Hibernate: select employee0_.emp_id as emp_id1_1_0_, employee0_.emp_name as emp_name2_1_0_, employee0_.emp_salary as emp_sala3_1_0_, address1_.emp_id as emp_id1_0_1_, address1_.address_line1 as address_2_0_1_, address1_.city as city3_0_1_, address1_.zipcode as zipcode4_0_1_ from EMPLOYEE employee0_ left outer join ADDRESS address1_ on employee0_.emp_id=address1_.emp_id where employee0_.emp_id=?
178:: Name=David, Zipcode=95051
18Session Contains Employee with id=2?true

Hibernate中的一级缓存要点

从上面的程序中可以得到的关于Hibernate中一级缓存的要点是:

1.默认开启Hibernate一级缓存,无需配置。 2.Hibernate一级缓存是特定于会话的,这就是为什么当我们在同一个会话中获取相同的数据时,不会触发查询,而在其他会话中,会触发查询来加载数据。 3.Hibernate一级缓存可以有旧的值,正如您在上面看到的,我让程序休眠了10秒,在此期间我更新了数据库中的值(名称从Pankaj到PankajK),但它没有在同一会话中反映出来。但在另一次会议上,我们得到了更新的价值。 4.我们可以使用会话evict()方法从Hibernate一级缓存中移除单个对象。 5.可以使用会话clear()方法清空缓存,即删除缓存中的所有对象。 6.我们可以使用会话containes()方法来检查对象是否存在于Hibernate缓存中,如果在缓存中找到该对象,则返回True,否则返回False。 7.由于Hibernate会将所有对象缓存到会话一级缓存中,因此在运行批量查询或批量更新时,需要定期清除缓存,以避免内存问题。

这就是Hibernate缓存和一级缓存的例子,在以后的文章中,我们将研究Hibernate二级缓存-EHCache实现。

Published At
Categories with 技术
Tagged with
comments powered by Disqus