簡體   English   中英

為什么我的Hibernate Query會返回陳舊數據?

[英]Why is my Hibernate Query returning stale data?

快速版

基本上,我正在更新一個Hibernate表,后續查詢正在加載一個陳舊的值。

詳細版本

Hibernate(3.3.1.GA)和EhCache(2.4.2)。

帶有List<PageContent>頁面的持久Book對象,我在本書的中間添加了一個頁面。 我正在使用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 :通過調試,我可以確認數據存儲區有正確的信息,當查詢運行時,它會回退到二級緩存 - 它有臟信息。 我認為每次數據發生變化時都不能從緩存中逐出?

CwmService.get().flushChanges(); // commits the transaction之后CwmService.get().flushChanges(); // commits the transaction CwmService.get().flushChanges(); // commits the transaction做一個顯式提交。 flush()僅將更改刷新到db但不提交。 我不確定flushChanges()

我發現了這個問題,但它引入了其他的東西。

基本上,在修改Book對象的List<PageContent>字段時,Hibernate會做三件事:

  1. 使BookPageContent的TimeStamp緩存條目PageContent
  2. 是否有許多查詢要重置每個PageContent對象上的pageNum字段
  3. 從二級緩存中刪除Book對象。

這可確保后續查詢將搜索新對象等。但是:

  1. Hibernate無法從二級緩存中刪除每個重新編號的PageContent對象

因此,對頁面列表的任何查詢都將正常運行,但隨后將回退到實際數據的過時二級緩存值。

我認為這是因為Hibernate感覺pageNum更改不是數據的變化,而是幕后管理的變化。 但是,這是我想要閱讀和顯示的數據。

解決方案是在插入/刪除發生后手動刷新每個頁面。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM