快速版
基本上,我正在更新一个休眠表,随后的查询正在加载一个陈旧的值。
详细版本
休眠 (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);
}
最终结果是列表中添加了一个新页面,数据库也相应更新,我已经在我的数据存储中确认了这一点。但是,对页面的下一个查询,例如“Page #4”,会加载“旧”Page #4 而不是新的 Page #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:通过调试,我可以确认数据存储具有正确的信息,并且当查询运行时,它会退回到二级缓存——它有脏信息。我认为每次数据更改时都不能从缓存中逐出?