3

在我的 applicationcontext.xml

<bean id="annotatedsessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="packagesToScan" value="testonly.package.model" />
<property name="hibernateProperties">
    <props>
        <prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.format_sql">true</prop>
        <prop key="hibernate.use_sql_comments">true</prop>
        <prop key="hibernate.cglib.use_reflection_optimizer">true</prop>
        <prop key="hibernate.hbm2ddl.auto">update</prop>
        <prop key="hibernate.c3p0.min_size">5</prop>
        <prop key="hibernate.c3p0.max_size">20</prop>
        <prop key="hibernate.c3p0.timeout">1800</prop>
        <prop key="hibernate.c3p0.max_statements">50</prop>
        <prop key="hibernate.cache.provider_class">
                org.hibernate.cache.EhCacheProvider
        </prop>
        <prop key="hibernate.cache.use_second_level_cache">true</prop>
        <prop key="hibernate.cache.use_query_cache">true</prop>
    </props>
</property>
<property name="dataSource">
    <ref bean="dataSource" />
</property>

在我的实体中

@Entity
@Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

@Table(name = "TestPOJOCATEGORY")
@NamedQueries({
 @NamedQuery(name = "TestPOJOcategory.findAll", query = "SELECT h FROM TestPOJOcategory h"),
 @NamedQuery(name = "TestPOJOcategory.findById", query = "SELECT h FROM TestPOJOcategory h WHERE h.id = :id"),
 @NamedQuery(name = "TestPOJOcategory.findByCategoryname", query = "SELECT h FROM TestPOJOcategory h WHERE h.categoryname = :categoryname")})
public class TestPOJOcategory implements Serializable {

在我的道

public List<TestPOJOcategory> getAllCategory(final String keyword, final int nFirst,
        final int nPageSize,
        final String sortColumnId,
        final boolean bSortOrder) {

  List<TestPOJOcategory> result = (List<TestPOJOcategory>) getHibernateTemplate().execute(new HibernateCallback() {
    public Object doInHibernate(Session session) {
      Criteria crit = session.createCriteria(TestPOJOcategory.class, "TestPOJOcategory")
       .add(Restrictions.ilike("categoryname", keyword))
       .addOrder(bSortOrder ? Order.asc(sortColumnId) : Order.desc(sortColumnId))
       .setFirstResult(nFirst).setMaxResults(nPageSize);
      System.out.println("why still call from DB? suppose to call from cache");
      return crit.list();
    }
  });
  return result;
}

echcache.xml

 <cache name="testonly.package.model.TestPOJOcategory"
        maxElementsInMemory="200"
        eternal="true"
        overflowToDisk="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
    />

每次我调用 dao 时,它仍然会从 DB 调用。为什么?

4

4 回答 4

6

首先,System.out.println()无论是否访问二级缓存,每次都将执行您的语句,因为此类访问发生在list()方法中。

其次,Criteria - 很像 Query - 不会自动使用二级缓存;您指定的配置属性仅允许使用它。您仍然需要通过调用将每个 Query / Criteria 实例显式标记为可缓存setCacheable(true)

Criteria crit = ...;
crit.setCacheable(true);
return crit.list();

附带说明一下,既然您正在使用HibernateTemplate它,您不妨正确使用它:-) 并摆脱手动doInHibernate包装器:

public List<TestPOJOcategory> getAllCategory(final String keyword, final int nFirst,
    final int nPageSize,
    final String sortColumnId,
    final boolean bSortOrder) {

  DetachedCriteria crit = DetachedCriteria.forClass(TestPOJOcategory.class);
  crit.add(Restrictions.ilike("categoryname", keyword))
   .addOrder(bSortOrder ? Order.asc(sortColumnId) : Order.desc(sortColumnId));
  getHibernateTemplate().setCacheQueries(true); // works on both queries and criteria
  return (List<TestPOJOcategory>) getHibernateTemplate()
   .findByCriteria(crit, nFirst, nPageSize);
}
于 2009-12-03T02:59:30.813 回答
5

好吧,使用二级缓存并不意味着您可以根据任意 HQL(或 Criteria)查询在缓存中找到对象。第二个缓存仅在通过其键访问对象或导航对象图时使用。

因此,在这里,您需要使用查询缓存(是的,有 3 个缓存:一级缓存、二级缓存和查询缓存)。这需要:

session.createQuery("query").setCacheable(true); 

或者,使用时Criteria

session.createCriteria(...).add(...).setCacheable(true);

和休眠属性集(你有):

hibernate.cache.use_second_level_cache=true
hibernate.cache.use_query_cache=true 

实际上,如果您想更好地了解 Hibernate 使用的各种缓存机制以及 Hibernate 缓存的确切内容(即“脱水”实体),我强烈建议您查看以下资源:

前两篇文章有点旧,但仍然适用。后者是最近的。都是好读物IMO。

于 2009-12-03T03:20:47.550 回答
1

如果您想知道是否执行了 SQL 语句,请打开 show_sql 属性(或 org.hibernate.SQL 记录器)。

否则,Hibernate 缓存主要是通过主键。这在需要刷新对象或遍历多对一关系时非常有用。通过可能会或可能不会影响结果集的随机并发更新/插入/删除来保持任意查询的缓存结果集一致似乎非常复杂。除非您有性能问题,否则我不建议缓存查询。

于 2009-12-03T03:22:45.940 回答
0

看起来您可能错过了在休眠级别上配置缓存。看起来您需要将以下内容添加到您的休眠配置文件中以启用缓存。

<cache usage=”read-only” />

您可能还想查看此链接,它看起来不错。 http://blog.dynatrace.com/2009/03/24/understanding-caching-in-hibernate-part-three-the-second-level-cache/

希望这有帮助!

于 2009-12-03T03:14:34.020 回答