質問

クイックバージョン

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

詳細バージョン

Hibernate(3.3.1.ga)とEhcache(2.4.2)。

Pagesの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の代わりに「古い」ページ#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" />
.

update :DataStoreオブジェクトの@Cacheアノテーションを削除すると、問題が解除されます。もちろん、ページ修正がアクセスよりはるかに少ないため、これらのオブジェクトをキャッシュしたいと思います。

だから考えて?ページを削除することを含む、他にも関連しています。すべてが期待どおりにデータベースを更新しますが、実際の動作は正しくありません。

事前にありがとう!

アップデート#2 :デバッグを介して、データストアに正しい情報があることを確認し、クエリが実行されると、ダーティ情報がある2レベルのキャッシュに戻ります。データが変わるたびにキャッシュから立ち退くように、私は私次第ではないと思いますか?

役に立ちましたか?

解決 2

I discovered the problem, but it introduces something else.

Basically, when modifying a Book object's List<PageContent> field, Hibernate does three things:

  1. Expires the TimeStamp cache entry for both Book and PageContent
  2. Does many queries to reset the pageNum field on each PageContent object
  3. Removes the Book object from the Second Level Cache.

This ensures that subsequent queries will search for new objects, etc. However:

  1. Hibernate fails to remove each renumbered PageContent object from the Second Level Cache

As a result, any query for the list of pages will run properly, but then will fall back on stale Second Level Cache values for the actual data.

I presume this is because Hibernate feels a pageNum change is not a change in data but a change in behind-the-scenes management. However, that is the data that I would like to read and display.

The solution is to manually refresh every page after the insertion/deletion has occurred.

他のヒント

After CwmService.get().flushChanges(); // commits the transaction do an explicit commit. flush() only flushes the changes to db but does not commit it. I am not sure about flushChanges() though.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top