English 中文(简体)
cannot do 2nd level cache
原标题:

in my 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>

In my Entity

@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 {

In My Dao

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"
    />

Each time I call the dao, it will still call from DB. Why?

最佳回答

First of all, your System.out.println() statement will get executed every time whether or not 2nd level cache is accessed because such access takes place within list() method.

Secondly, Criteria - much like Query - does not automatically use 2nd level cache; configuration properties you ve specified merely enable it to be used. You still need to explicitly mark each Query / Criteria instance as cacheable by calling setCacheable(true):

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

On a side note, since you re using HibernateTemplate you might as well use it right :-) and get rid of manual doInHibernate wrapper:

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);
}
问题回答

Well, using the second level cache doesn t mean that you can find an object in the cache based on any arbitrary HQL (or Criteria) query. The second cache is only used when accessing the object by its key or when navigating an object graph.

So, here, you ll need to use query caching (yes, there are 3 caches: the first level cache, the second level cache and the query cache). This needs:

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

Or, when using Criteria:

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

And hibernate properties set (which you have):

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

Actually, I d warmly suggest to check the following resources if you want to get a better understanding of the various caching mechanism Hibernate uses and of what Hibernate caches exactly (i.e. "dehydrated" entities):

The two first articles are a bit old but still apply. The later is more recent. All are good readings IMO.

If you want to know if a SQL statement gets executed, then turn on the show_sql property on (or the org.hibernate.SQL logger).

Otherwise, Hibernate caching is mainly by primary key. This makes is very useful when an object needs to be refreshed or many-to-one relationships are traversed. Keeping a cached result set for an arbitrary query consistent through random concurrent updates/inserts/deletes that may or may not impact the result set seems very complicated. Unless you have a performance problem I wouldn t recommend caching queries.

It looks like you may have missed configuring the cache on the hibernate level. It looks like you need to add the following to your hibernate configuration file to enable caching.

<cache usage=”read-only” />

You also may want to check this link out, it looks pretty good. http://blog.dynatrace.com/2009/03/24/understanding-caching-in-hibernate-part-three-the-second-level-cache/

Hope this is helpful!





相关问题
Spring Properties File

Hi have this j2ee web application developed using spring framework. I have a problem with rendering mnessages in nihongo characters from the properties file. I tried converting the file to ascii using ...

Logging a global ID in multiple components

I have a system which contains multiple applications connected together using JMS and Spring Integration. Messages get sent along a chain of applications. [App A] -> [App B] -> [App C] We set a ...

Java Library Size

If I m given two Java Libraries in Jar format, 1 having no bells and whistles, and the other having lots of them that will mostly go unused.... my question is: How will the larger, mostly unused ...

How to get the Array Class for a given Class in Java?

I have a Class variable that holds a certain type and I need to get a variable that holds the corresponding array class. The best I could come up with is this: Class arrayOfFooClass = java.lang....

SQLite , Derby vs file system

I m working on a Java desktop application that reads and writes from/to different files. I think a better solution would be to replace the file system by a SQLite database. How hard is it to migrate ...

热门标签