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()内で行われるため、第 2 レベルのキャッシュにアクセスするかどうかにかかわらず、ステートメントは毎回実行されます。list()

第 2 に、Criteria (Query と同様)は自動的に 2 次キャッシュを使用しません。指定した構成プロパティは、それを使用できるようにするだけです。以下を呼び出して、各 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

2 番目のレベルのキャッシュを使用しても、任意の HQL (または Criteria) クエリに基づいてキャッシュ内のオブジェクトを見つけることができるわけではありません。2 番目のキャッシュは、キーによってオブジェクトにアクセスするとき、またはオブジェクト グラフをナビゲートするときにのみ使用されます。

したがって、ここでは、クエリ キャッシュを使用する必要があります(そうです、3 つのキャッシュがあります。1 番目のレベルのキャッシュ、2 番目のレベルのキャッシュ、およびクエリのキャッシュです)。これには次が必要です。

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 が正確にキャッシュするもの (つまり、「脱水された」エンティティ) をよりよく理解したい場合は、次のリソースを確認することを強くお勧めします。

最初の 2 つの記事は少し古いですが、まだ適用されます。後のほうが最近です。すべてが良い読書 IMO です。

于 2009-12-03T03:20:47.550 に答える
1

SQLステートメントが実行されるかどうかを知りたい場合は、show_sqlプロパティをオンにします(またはorg.hibernate.SQLロガー)。

それ以外の場合、Hibernateキャッシングは主に主キーによって行われます。これは、オブジェクトを更新する必要がある場合、または多対1の関係をトラバースする場合に非常に役立ちます。結果セットに影響を与える場合と影響を与えない場合があるランダムな同時更新/挿入/削除を通じて、任意のクエリのキャッシュされた結果セットの一貫性を維持することは非常に複雑に思えます。パフォーマンスの問題がない限り、クエリをキャッシュすることはお勧めしません。

于 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 に答える