1、在hibernate.cfg.xml中加入查詢緩存的策略, <propertyname="hibernate.cache.use_query_cache">true</property>
啟用查詢緩存的策略,默認是false。
二、關閉二級緩存,采用query.list()查詢普通屬性
代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public voidtestCache1() { Session session = null ; try { session= HibernateUtils.getSession(); session.beginTransaction(); Listnames = session.createQuery( "select s.name from Student s" ) .setCacheable( true ) .list(); for ( int i= 0 ;i<names.size(); i++) { Stringname = (String)names.get(i); System.out.println(name); } System.out.println( "-------------------------------------------------------" ); //不會發出查詢語句,因為啟用查詢緩存 names= session.createQuery( "select s.name from Student s" ) .setCacheable( true ) .list(); for ( int i= 0 ;i<names.size(); i++) { Stringname = (String)names.get(i); System.out.println(name); } session.getTransaction().commit(); } catch (Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } } |
我們可以看到控制臺輸出語句,僅輸出一次:Hibernate: select student0_.name as col_0_0_ fromt_student student0_
由此可知,我們開啟了查詢緩存,第一次進行查詢的時候,已經把結果放到querycache中,當第二次再次做出相同的查詢的時候,就不再向數據庫發重復的sql語句了。
三、關閉二級緩存,啟用查詢緩存,采用query.list()查詢普通屬性
代碼就如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
public voidtestCache2() { Sessionsession = null ; try { session= HibernateUtils.getSession(); session.beginTransaction(); Listnames = session.createQuery( "select s.name from Student s" ) .setCacheable( true ) .list(); for ( int i= 0 ;i<names.size(); i++) { Stringname = (String)names.get(i); System.out.println(name); } session.getTransaction().commit(); } catch (Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } System.out.println( "-------------------------------------------------------" ); try { session= HibernateUtils.getSession(); session.beginTransaction(); //不會發出查詢語句,因為查詢緩存和session的生命周期沒有關系 Listnames = session.createQuery( "select s.name from Student s" ) .setCacheable( true ) .list(); for ( int i= 0 ;i<names.size(); i++) { Stringname = (String)names.get(i); System.out.println(name); } session.getTransaction().commit(); } catch (Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } } |
運行結果如下所示。
控制臺打印結果:
select student0_.name as col_0_0_ fromt_student student0_
班級0的學生0
班級0的學生1
班級0的學生2
班級0的學生3
班級0的學生4
班級0的學生5…
我們可以看出,同樣,只打印一次查詢語句,如果沒有開啟查詢緩存的話,并且關閉二級緩存的情況下,還會去數據庫再查詢一遍,而我們的程序中沒有再去重復的去數據庫中查詢的原因是,當開啟query緩存的時候,查詢緩存的生命周期與session無關。
四、關閉二級緩存,開啟查詢,采用query.iterate()查詢普通屬性
代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
public voidtestCache3() { Sessionsession = null ; try { session= HibernateUtils.getSession(); session.beginTransaction(); Iteratoriter = session.createQuery( "select s.name from Student s" ) .setCacheable( true ) .iterate(); while (iter.hasNext()){ Stringname = (String)iter.next(); System.out.println(name); } session.getTransaction().commit(); } catch (Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } System.out.println( "-------------------------------------------------------" ); try { session= HibernateUtils.getSession(); session.beginTransaction(); //會發出查詢語句,query.iterate()查詢普通屬性它不會使用查詢緩存 //查詢緩存只對query.list()起作用 Iteratoriter = session.createQuery( "select s.name from Student s" ) .setCacheable( true ) .iterate(); while (iter.hasNext()){ Stringname = (String)iter.next(); System.out.println(name); } session.getTransaction().commit(); } catch (Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } } |
顯控制臺顯示結果打印了兩次sql語句。
-------------------------------------------------------
1
|
Hibernate: select student0_.name as col_0_0_from t_student student0_ |
根據這樣的結果我們發現,quer.iterate()
查詢普通屬性它是不會使用查詢緩存,查詢緩存只對query.list()起作用。
五、關閉二級緩存,關閉查詢緩存,采用query.list()查詢實體
代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
public voidtestCache4() { Sessionsession = null ; try { session= HibernateUtils.getSession(); session.beginTransaction(); List students =session.createQuery( "select s from Student s" ) .list(); for ( int i= 0 ;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } session.getTransaction().commit(); } catch (Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } System.out.println( "-------------------------------------------------------" ); try { session= HibernateUtils.getSession(); session.beginTransaction(); //會發出查詢語句,默認query.list()每次執行都會發出查詢語句 List students =session.createQuery( "select s from Student s" ) .list(); for ( int i= 0 ;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } } catch (Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } } |
顯示結果如下所示。
控制臺上打印兩次sql語句。
1
|
Hibernate:select student0_.id as id0_, student0_.name as name0_, student0_.classesid asclassesid0_ from t_student student0_ |
班級0的學生0
班級0的學生1
班級0的學生2
班級0的學生3
班級0的學生4
由此可知,不開啟查詢緩存,默認query.list每次執行都會發出查詢語句。
六、關閉二級緩存,開啟查詢緩存,采用query.list()查詢實體
代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
Session session = null ; try { session= HibernateUtils.getSession(); session.beginTransaction(); Liststudents = session.createQuery( "select s from Student s" ) .setCacheable( true ) .list(); for ( int i= 0 ;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } session.getTransaction().commit(); } catch (Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } System.out.println( "-------------------------------------------------------" ); try { session= HibernateUtils.getSession(); session.beginTransaction(); //會發出n條查詢語句,因為開啟了查詢緩存,關閉了二級緩存,那么查詢緩存就會緩存實體對象的id //第二次執行query.list(),將查詢緩存中的id依次取出,分別到一級緩存和二級緩存中查詢相應的實體 //對象,如果存在就使用緩存中的實體對象,否則根據id發出查詢學生的語句 Liststudents = session.createQuery( "select s from Student s" ) .setCacheable( true ) .list(); for ( int i= 0 ;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } } catch (Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } |
控制臺打印sql如下圖所示。
在第一次查詢的時候,發出一條sql語句查詢出結果,因為我們開啟了查詢緩存,會把第一次查詢出的實體結果集的id放到查詢緩存中,第二次再次執行query.list()的時候,會把id拿出來,到相應的緩存去找,因為是跨session,在二級緩存中找不到,所以每次都會發出查詢語句,二級緩存中不存在,有多少個id就會發出查詢語句多少次。
七、開啟二級緩存,開啟查詢緩存,采用query.list()查詢實體
代碼如下所示。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
|
/** * 開啟查詢,開啟二級緩存,采用query.list()查詢實體 * * 在兩個session中發query.list()查詢 */ public voidtestCache6() { Sessionsession = null ; try { session= HibernateUtils.getSession(); session.beginTransaction(); Liststudents = session.createQuery( "select s from Student s" ) .setCacheable( true ) .list(); for ( int i= 0 ;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } session.getTransaction().commit(); } catch (Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } System.out.println( "-------------------------------------------------------" ); try { session= HibernateUtils.getSession(); session.beginTransaction(); //不再發出查詢語句,因為配置了二級緩存和查詢緩存 Liststudents = session.createQuery( "select s from Student s" ) .setCacheable( true ) .list(); for ( int i= 0 ;i<students.size(); i++) { Studentstudnet = (Student)students.get(i); System.out.println(studnet.getName()); } } catch (Exceptione) { e.printStackTrace(); session.getTransaction().rollback(); } finally { HibernateUtils.closeSession(session); } } |
結果如下所示
1
|
Hibernate: select student0_.id as id0_,student0_.name as name0_, student0_.classesid as classesid0_ from t_studentstudent0_ |
只發出一次sql請求,當我們第一次執行query.list()會放到二級緩存中,和query緩存中。當我們第一次執行查詢時,會找到相應的id到緩存中查找,在二級緩存中存在,則直接從二級緩存中取出數據,不再向數據庫中發出sql語句。
八、查詢緩存總結
查詢緩存是緩存普通屬性結果集的,對實體對象的結果集會緩存id。查詢緩存的生命周期,當關聯的表發生修改時,查詢緩存的生命周期結束。
而開啟緩存的時候,我們就要去維護緩存,如果緩存和內存中的數據不一致的話,和數據不同步,可能給用戶顯示的是臟數據了。所以根據需要使用緩存機制。
總結
以上所述是小編給大家介紹的hibernate查詢緩存詳細分析,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對服務器之家網站的支持!
原文鏈接:http://blog.sina.com.cn/s/blog_9c6852670102wvhj.html