4

クイックバージョン

基本的に、Hibernateテーブルを更新していて、後続のクエリが古い値をロードしています。

詳細版

Hibernate(3.3.1.GA)およびEhCache(2.4.2)。

ページ数のある永続化Bookされたオブジェクトで、List<PageContent>この本の真ん中にページを追加しています。私はDatabinder/Wicketを使用していますが、それは関連しているとは思いません。

 public void createPageContent(Book book, int index) {
     Databinder.getHibernateSession().lock(book, LockMode.UPGRADE);
     PageContent page = new PageContent(book);
     book.addPage(page, index);
     CwmService.get().flushChanges(); // commits the transaction
 }

の該当するフィールド/メソッドは次のBookとおりです。

@OneToMany
@JoinColumn(name="book_id")
@IndexColumn(name="pageNum")
@Cascade({CascadeType.ALL, CascadeType.DELETE_ORPHAN})
private List<PageContent> pages = new ArrayList<PageContent>();

public synchronized void addPage(PageContent page, int index) {
    pages.add(index, page);
}

その結果、リストに新しいページが追加され、それに応じてデータベースが更新され、データストアでこれを確認しました。ただし、ページの次のクエリ、たとえば「ページ#4」は、新しいページ#4ではなく「古い」ページ#4をロードします。

criteria.add(Restrictions.eq("book", book));
criteria.add(Restrictions.eq("pageNum", pageNum));
criteria.setCacheable(true);  

それで、私は惜しみなく基準からキャッシングを削除します。データストアにクエリを実行しますが、それでも間違った値を返します。ただし、どちらの場合も、2分ほど待つと、すべてが期待どおりに機能しています。キャッシングはまだ関係していると思います。両方ともPageContentBookこのキャッシュ戦略を使用します。

@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)

私はキャッシングに不慣れで、このファイルを初めて設定したことを告白します。これが私のehcache.xmlです:

<defaultCache maxElementsInMemory="10000" eternal="false" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true" diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000" diskPersistent="false" diskExpiryThreadIntervalSeconds="120" memoryStoreEvictionPolicy="LRU" statistics="false"/>

<!-- Hibernate's Cache for keeping 'lastUpdated' data on each table.  Should never expire. -->
<cache name="org.hibernate.cache.UpdateTimestampsCache" eternal="true" />

<!-- Hibernate's Query Cache - should probably be limited -->
<cache name="org.hibernate.cache.StandardQueryCache" maxElementsInMemory="1000" />

更新@Cacheデータストアオブジェクトの注釈を削除すると、問題が削除されます。もちろん、ページの変更はアクセスよりもはるかに少ないため、これらのオブジェクトをキャッシュしたいと思います。

それで、考え?ページの削除など、他にもいくつかの問題があります。すべてが期待どおりにデータベースを更新しますが、実際の動作は不安定です。

前もって感謝します!

更新#2:デバッグを介して、データストアに正しい情報があることを確認できます。クエリを実行すると、ダーティ情報が含まれている第2レベルのキャッシュにフォールバックします。データが変更されるたびにキャッシュから削除するのは私次第ではないと思いますか?

4

2 に答える 2

0

CwmService.get().flushChanges(); // commits the transaction明示的なコミットを行った 後。flush()変更を db にフラッシュするだけで、コミットはしません。よくわかりませんflushChanges()が。

于 2011-05-19T20:44:47.957 に答える
0

私は問題を発見しましたが、それは別のものをもたらします。

基本的に、BookオブジェクトのList<PageContent>フィールドを変更するとき、Hibernate は次の 3 つのことを行います。

  1. Bookとの両方の TimeStamp キャッシュ エントリを期限切れにします。PageContent
  2. 各オブジェクトのpageNumフィールドをリセットするために多くのクエリを実行しますPageContent
  3. Book第 2 レベル キャッシュからオブジェクトを削除します。

これにより、後続のクエリが新しいオブジェクトなどを検索することが保証されます。ただし:

  1. Hibernate が再番号付けされPageContentた各オブジェクトをセカンド レベル キャッシュから削除できない

その結果、ページのリストに対するクエリは適切に実行されますが、実際のデータの古い 2 次キャッシュ値にフォールバックします。

これは、Hibernate がpageNum変更はデータの変更ではなく、舞台裏の管理の変更であると感じているためだと思います。しかし、それは私が読んで表示したいデータです。

解決策は、挿入/削除が発生した後にすべてのページを手動で更新することです。

于 2011-05-25T16:37:36.290 に答える