[英]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分鍾,一切都按預期工作。 我認為緩存仍然存在。 PageContent
和Book
使用此緩存策略:
@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會做三件事:
Book
和PageContent
的TimeStamp緩存條目PageContent
PageContent
對象上的pageNum
字段 Book
對象。 這可確保后續查詢將搜索新對象等。但是:
PageContent
對象 因此,對頁面列表的任何查詢都將正常運行,但隨后將回退到實際數據的過時二級緩存值。
我認為這是因為Hibernate感覺pageNum
更改不是數據的變化,而是幕后管理的變化。 但是,這是我想要閱讀和顯示的數據。
解決方案是在插入/刪除發生后手動刷新每個頁面。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.