ITEEDU

Hibernate Gossip: Query 快取

Hibernate的 Session level 快取 会在使用Session的load()方法时起作用,在设定条件进行查询时,无法使用快取的功能,现在考虑一种情况,您的数据库表格中的数据很少变动,在 使用Query查询数据时,如果表格内容没有变动,您希望能重用上一次查询的结果,除非表格内容有变动才向数据库查询。

您可以开启Query的快取功能,因为要使用Query的快取功能必须在两次查询时所使用的SQL相同,且两次查询之间表格没有任何数据变动下才有意义, 所以Hibernate预设是关闭这个功能的,如果您觉得符合这两个条件,那么可以试着开启Query快取功能来看看效能上有无改进。

先来看看下面的查询程序片段:
Session session = sessionFactory.openSession();

String hql = "from User";

Query query = session.createQuery(hql);
List users = query.list();

for(int i = 0; i < users.size(); i++) {
    User user = (User) users.get(i);
    System.out.println(user.getName());
}

query = session.createQuery(hql);
users = query.list();

for(int i = 0; i < users.size(); i++) {
    User user = (User) users.get(i);
    System.out.println(user.getName());
}

session.close();
在不启用Query快取的情况下,Hibernate会使用两次SQL向数据库查询数据:
Hibernate: select user0_.id as id, user0_.name as name0_, user0_.age as age0_ from user user0_
momor
caterpillar
Hibernate: select user0_.id as id, user0_.name as name0_, user0_.age as age0_ from user user0_
momor
caterpillar
如果打算启用Query快取功能,首先在hibernate.cfg.xml中设定hibernate.cache.use_query_cache属性:
hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

<session-factory>
....

<property name="hibernate.cache.use_query_cache">true</property>
....

</session-factory>

</hibernate-configuration>
然后在每次建立Query实例时,执行setCacheable(true):
Session session = sessionFactory.openSession();

String hql = "from User";

Query query = session.createQuery(hql);
// 使用Query快取
query.setCacheable(true);
List users = query.list();

for(int i = 0; i < users.size(); i++) {
    User user = (User) users.get(i);
    System.out.println(user.getName());
}

query = session.createQuery(hql);
// 使用Query快取
query.setCacheable(true);
users = query.list();

for(int i = 0; i < users.size(); i++) {
    User user = (User) users.get(i);
    System.out.println(user.getName());
}

session.close();
Hibernate在启用Query快取后,会保留执行过的查询SQL与查询结果,在下一次查询时会看看SQL是否相同,并看看对应的数据库表格是否有变 动(Update/Delete/Insert),如果SQL相同且数据库也没有变动,则将Query快取中的查询结果返回,上面的程序片段将使用一次 SQL查询,第二次查询时直接返回快取中的结果:
Hibernate: select user0_.id as id, user0_.name as name0_, user0_.age as age0_ from user user0_
momor
caterpillar
momor
caterpillar