java - 为什么我的 Hibernate 查询返回陈旧数据?

标签 java hibernate wicket ehcache databinder

快速版

基本上,我正在更新一个 Hibernate 表,而后续查询正在加载一个过时的值。

详细版

Hibernate (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 分钟,一切都会按预期进行。我认为仍然涉及缓存。两者 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() 之后;//提交事务 进行显式提交。 flush() 仅将更改刷新到数据库但不提交。不过,我不确定 flushChanges()

关于java - 为什么我的 Hibernate 查询返回陈旧数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6064083/

相关文章:

java - Wicket - 使用复选框禁用/启用文本字段

java - 在 JFileChooser 中调整 JList 文件元素的大小

java - 无法将项目列表发送到后端以从列表中删除

java - Hibernate Table 未找到、MappingException 和 AssertionException

hibernate - 在 grails 事务上捕获 RuntimeExceptions

java - Wicket - DropDownChoice - 选项的标题(工具提示)

java - java 类上的接口(interface)

java - 在 ParallelStream 中配置线程

java - 当用户已经登录时从 CAS 登录页面重定向

java - 将参数传递给 DAO 以获取 wicket 模型中的过滤结果