为什么我的Hibernate查询返回陈旧的数据? [英] Why is my Hibernate Query returning stale data?
问题描述
b
$ b
详细版本 坚持持有 最终结果是有一个新页面添加到列表中,数据库相应地更新,我已经在我的数据存储中证实了这一点。然而,下一个页面查询,比如说Page#4,会加载旧页面#4而不是新页面#4: 所以,我勉强地从标准中删除缓存。它查询数据存储,但是仍然返回错误的值。但是,在这两种情况下,如果我等待大约2分钟,一切都按预期工作。我认为缓存仍然涉及。 我承认我对于缓存来说并不陌生,只是第一次设置这个文件。这里是我的ehcache.xml: 更新:删除 所以,想法?还有其他几个相关问题,包括删除页面。一切都按预期更新数据库,但实际行为是不可靠的。 预先感谢! UPDATE#2 :通过调试,我可以确认数据存储具有正确的信息,并且在查询运行时,它会回退到二级缓存 - 它具有脏信息。我认为每当数据发生变化时,我无法从缓存中逐出?
账簿具有
的对象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(); //提交事务
}
Book
为:
@OneToMany
@JoinColumn(name =book_id)
@IndexColumn(name =pageNum)
@Cascade({CascadeType.ALL,CascadeType.DELETE_ORPHAN})
private List< PageContent> pages = new ArrayList< Page Content>();
public synchronized void addPage(PageContent page,int index){
pages.add(index,page);
}
criteria.add(Restrictions.eq(book,book));
criteria.add(Restrictions.eq(pageNum,pageNum));
criteria.setCacheable(true);
PageContent
和 Book
使用此缓存策略:
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
< defaultCache maxElementsInMemory =10000eternal =falsetimeToIdleSeconds =120timeToLiveSeconds = 120overflowToDisk =truediskSpoolBufferSizeMB =30maxElementsOnDisk =10000000diskPersistent =falsediskExpiryThreadIntervalSeconds =120memoryStoreEvictionPolicy =LRUstatistics =false/>
<! - Hibernate's Cache用于在每个表上保存'lastUpdated'数据。永远不会过期。 - >
< cache name =org.hibernate.cache.UpdateTimestampsCacheeternal =true/>
<! - Hibernate的查询缓存 - 可能应该是有限的 - >
< cache name =org.hibernate.cache.StandardQueryCachemaxElementsInMemory =1000/>
@Cache 我的数据存储对象上的code>注释消除了这个问题。当然,我想缓存这些对象,因为页面修改比访问要少得多。
我发现了这个问题,但它基本上,当修改 Book 对象的
List< PageContent>
字段,Hibernate会做三件事:
- 将
Book
和PageContent
- 是否有许多查询重置
pageNum $ c $每个
PageContent
对象 - 的
c>字段将 Book 第二级缓存。
这可以确保后续查询将搜索新对象等。但是:
- Hibernate无法从第二级缓存中删除每个重新编号的
PageContent
对象 - Expires the TimeStamp cache entry for both
Book
andPageContent
- Does many queries to reset the
pageNum
field on eachPageContent
object - Removes the
Book
object from the Second Level Cache. - Hibernate fails to remove each renumbered
PageContent
object from the Second Level Cache
ol>
因此,对页面列表的任何查询都可以正常运行,但是随后w我认为这是因为Hibernate感觉到 pageNum
>变化不是数据的变化,而是幕后管理的变化。但是,这是我想要阅读和显示的数据。
解决方案是在插入/删除发生后手动刷新每个页面。
Quick Version
Basically, I'm updating a Hibernate Table and subsequent queries are loading a stale value.
Detailed Version
Hibernate (3.3.1.GA) and EhCache (2.4.2).
Persisted Book
object with a List<PageContent>
of pages and I'm adding a page to the middle of this book. I'm using Databinder/Wicket, though I do not think that is related.
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
}
The applicable fields/method in Book
are:
@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);
}
The end result is that there is a new page added to a list and the database is updated accordingly and I've confirmed this in my datastore. However, the next query for a page, say "Page #4," loads the "old" Page #4 instead of the new Page #4:
criteria.add(Restrictions.eq("book", book));
criteria.add(Restrictions.eq("pageNum", pageNum));
criteria.setCacheable(true);
So, I grudgingly remove caching from the criteria. It queries the datastore, but still returns the wrong value. However, in both cases, if I wait about 2 minutes, everything is working as expected. I presume caching is still involved. Both PageContent
and Book
use this caching strategy:
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
I confess I'm new to caching and just set up this file for the first time. Here's my 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: Removing the @Cache
annotations on my datastore objects removes the problem. Of course, I would like to cache these objects because page modification is much less frequent than access.
So, thoughts? There are several other issues related as well, including with deleting pages. Everything updates the database as expected, but actual behavior is wonky.
Thanks in advance!
UPDATE #2: Via debugging, I can confirm that the Datastore has the correct information and when the query runs, it falls back on the Second-Level Cache - which has dirty information. I presume it's not up to me to evict from the cache every time the data changes?
I discovered the problem, but it introduces something else.
Basically, when modifying a Book
object's List<PageContent>
field, Hibernate does three things:
This ensures that subsequent queries will search for new objects, etc. However:
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.
这篇关于为什么我的Hibernate查询返回陈旧的数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!