当前位置: 首页 > 面试题库 >

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

马欣德
2023-03-14
问题内容

快速版本

基本上,我正在更新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);
}

最终结果是,有一个新页面添加到列表中,并且数据库也进行了相应更新,我已经在我的数据存储中确认了这一点。但是,对页面的下一个查询(例如“页面#4”)将加载“旧”页面#4,而不是新页面#4:

criteria.add(Restrictions.eq("book", book));
criteria.add(Restrictions.eq("pageNum", pageNum));
criteria.setCacheable(true);

因此,我勉强从条件中删除了缓存。它查询数据存储,但 仍返回错误的value
。但是,在两种情况下,如果我等待约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
:通过调试,我可以确认数据存储区具有正确的信息,并且当查询运行时,它会退回到具有脏信息的二级缓存中。我想是不是每次数据更改时都要从缓存中逐出?


问题答案:

我发现了问题,但引入了其他问题。

基本上,在修改Book对象的List<PageContent>字段时,Hibernate会执行三件事:

  1. 过期两个时间戳缓存条目BookPageContent
  2. 进行许多查询以重置pageNum每个PageContent对象上的字段
  3. Book从二级缓存中删除对象。

这样可以确保后续查询将搜索新对象等。但是:

  1. Hibernate无法PageContent从二级缓存中删除每个重新编号的对象

结果,对页面列表的任何查询都将正常运行,但随后将退回到实际数据的陈旧二级缓存值。

我认为这是因为Hibernate认为pageNum更改不是数据更改,而是后台管理的更改。但是,这就是我要读取和显示的数据。

解决方案是在插入/删除发生后手动刷新每个页面。



 类似资料:
  • 问题内容: 我有一堆应聘者,他们有一些或多个工作,每个人都在公司工作,并且使用了一些技能。 坏的ascii艺术如下: 这是我的数据库: 。 。 。 。 这是我对查询的尝试(请注意,我打算将通配符更改为字段名称;我只是想使某些功能生效): HediSql说 查询出了什么问题?我希望从不良的ascii艺术中可以清楚地知道我要达到的目标。 (此外,它对我连接表的顺序是否有任何速度差异?我将担心新的MyS

  • 我正在查询SQL数据库,但由于某些原因,结果项会随机返回。这是我的密码: searchFriendEmailArrayNew是一个电子邮件地址数组,因此当我查询数据库表时,它会使用电子邮件来查找该用户。数组始终保持一致且顺序相同: user1@email.com 查询总是按照这个顺序进行的。 然后,我查询用户的所选字段,在本例中,我查询的是“isriding”字段。此字段是返回true或false

  • 我们使用1.3.5版本创建了一个spring boot项目。我们的应用程序与Mysql数据库交互。我们创建了一组JPA存储库,在其中我们使用了findAll、findOne和其他自定义查询方法。 我们正面临一个随机出现的问题。以下是复制它的步骤: > 使用spring启动应用程序在数据库上启动读取查询。 现在,使用mysql-console手动更改上面读取查询返回的记录的Mysql中的数据。 再次

  • 问题内容: 今天,我写了一个查询,应该返回一个错误。而是返回带有列名和数据类型的值15 。你知道为什么吗? 结果: 问题答案: 您要指定一个常量: 货币常量表示为数字字符串,带有可选的小数点 和可选的货币符号作为前缀 因此moneyselect $15select ¥15`。 正如Jeroen在评论中指出的那样: 因为日元符号(楼)是货币指示器,并且在某些日语本机字符集中,其代码点与ASCII中的

  • 问题内容: 环境 hibernate4.2 ojdbc6-Oracle 11.2.0.3.0 JDBC 4.0 Oracle数据库11g 问题 我们遵循了许多建议,以如下方式配置Hibernate批处理: 我们检查了日志,发现生成的SQL语句已批处理。但是,如果两个事务同时修改相同版本的实体行,则Hibernate将成功提交它们,导致最后提交的事务中的冲突更新丢失(两个事务中都保存了无冲突的数据,