hibernate查询缓存有不同数量的sql而没有L2缓存

时间:2015-12-13 08:17:16

标签: hibernate caching

我正在使用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>

1 个答案:

答案 0 :(得分:1)

我假设你启用了查询缓存。

在第一种情况下,您打开第一个会话并首次执行查询。查询缓存将填充查询返回的学生的ID。 L2缓存已禁用,因此学生不会存储在其中。然后打开第二个会话并执行相同的查询。从查询缓存中检索ID而不触及数据库。但是Hibernate一个接一个地让学生们参加会议。由于会话是新的,它们不在会话中,并且它们也不在L2缓存中。所以它必须为每个学生打到数据库。

在第二种情况下,您在同一会话中执行所有操作。因此,首先执行查询,并将ID存储在查询缓存中。然后执行相同的查询。 ID位于查询缓存中,Hibernate从会话中获取每个学生。它们已经存在,因为第一个查询填充了会话。

故事的故事:启用查询缓存而不是L2缓存是浪费资源:你最终会得到更多的查询,因为你会强制Hibernate通过数据库中的ID获取实体,一。不要那样做。