我正在使用hibernate 4.3.10,启用查询缓存,没有L2缓存, 测试以下代码(称之为 Part1 ):
Session s1 = sessionFactory.openSession();
List<StudentQuery> students = s1.createQuery("from StudentQuery").setCacheable(true).list();
s1.close();
Session s2 = sessionFactory.openSession();
List<StudentQuery> stus = s2.createQuery("from StudentQuery").setCacheable(true).list();
sessionFactory.close();
以下是输出:
Hibernate: select studentque0_.id as id1_5_, studentque0_.age as age2_5_, studentque0_.name as name3_5_ from student studentque0_
Hibernate: select studentque0_.id as id1_5_0_, studentque0_.age as age2_5_0_, studentque0_.name as name3_5_0_ from student studentque0_ where studentque0_.id=?
Hibernate: select studentque0_.id as id1_5_0_, studentque0_.age as age2_5_0_, studentque0_.name as name3_5_0_ from student studentque0_ where studentque0_.id=?
Hibernate: select studentque0_.id as id1_5_0_, studentque0_.age as age2_5_0_, studentque0_.name as name3_5_0_ from student studentque0_ where studentque0_.id=?
Hibernate: select studentque0_.id as id1_5_0_, studentque0_.age as age2_5_0_, studentque0_.name as name3_5_0_ from student studentque0_ where studentque0_.id=?
Hibernate: select studentque0_.id as id1_5_0_, studentque0_.age as age2_5_0_, studentque0_.name as name3_5_0_ from student studentque0_ where studentque0_.id=?
Hibernate: select studentque0_.id as id1_5_0_, studentque0_.age as age2_5_0_, studentque0_.name as name3_5_0_ from student studentque0_ where studentque0_.id=?
但是,对于下一个代码(称之为 Part2 ):
Session s1 = sessionFactory.openSession();
List<StudentQuery> students = s1.createQuery("from StudentQuery").setCacheable(true).list();
List<StudentQuery> students2 = s1.createQuery("from StudentQuery").setCacheable(true).list();
sessionFactory.close();
输出是:
Hibernate: select studentque0_.id as id1_5_, studentque0_.age as age2_5_, studentque0_.name as name3_5_ from student studentque0_
为什么输出不同? Part1中有7个hql语句,而Part2中只有一个。
实体是(我评论@Cache禁用L2缓存):
@Entity
@Table(name="student")
//@Cache(usage=CacheConcurrencyStrategy.READ_ONLY,region="student")
public class StudentQuery {
.....
}
hibernate.cfg.xml如下所示:
<hibernate-configuration>
<session-factory>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">jdbc:mysql://localhost/test</property>
<property name="connection.username">test</property>
<property name="connection.password">abc</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.pool_size">1</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.cache.region.factory_class">
org.hibernate.cache.ehcache.EhCacheRegionFactory
</property>
<property name="hibernate.cache.use_second_level_cache">true</property>
<property name="net.sf.ehcache.configurationResourceName">
resources/ehcache.xml
</property>
<property name="show_sql">true</property>
<property name="hbm2ddl.auto">update</property>
<property name="hibernate.cache.use_query_cache">true</property>
<mapping resource="resources/event.hbm.xml"/>
<mapping resource="resources/person.hbm.xml"/>
<mapping class="com.my.hibernate.basic.Student" />
<mapping class="com.my.hibernate.basic.StudentL2" />
<mapping class="com.my.hibernate.basic.StudentQuery" />
</session-factory>
</hibernate-configuration>
答案 0 :(得分:1)
我假设你启用了查询缓存。
在第一种情况下,您打开第一个会话并首次执行查询。查询缓存将填充查询返回的学生的ID。 L2缓存已禁用,因此学生不会存储在其中。然后打开第二个会话并执行相同的查询。从查询缓存中检索ID而不触及数据库。但是Hibernate一个接一个地让学生们参加会议。由于会话是新的,它们不在会话中,并且它们也不在L2缓存中。所以它必须为每个学生打到数据库。
在第二种情况下,您在同一会话中执行所有操作。因此,首先执行查询,并将ID存储在查询缓存中。然后执行相同的查询。 ID位于查询缓存中,Hibernate从会话中获取每个学生。它们已经存在,因为第一个查询填充了会话。
故事的故事:启用查询缓存而不是L2缓存是浪费资源:你最终会得到更多的查询,因为你会强制Hibernate通过数据库中的ID获取实体,一。不要那样做。