为什么我的Hibernate查询返回陈旧的数据? [英] Why is my Hibernate Query returning stale data?

查看:261
本文介绍了为什么我的Hibernate查询返回陈旧的数据?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,我正在更新一个Hibernate Table,随后的查询正在加载一个陈旧的值。

b
$ b

详细版本

Hibernate(3.3.1.GA)和EhCache(2.4.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);
}

最终结果是有一个新页面添加到列表中,数据库相应地更新,我已经在我的数据存储中证实了这一点。然而,下一个页面查询,比如说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 =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 注释消除了这个问题。当然,我想缓存这些对象,因为页面修改比访问要少得多。



所以,想法?还有其他几个相关问题,包括删除页面。一切都按预期更新数据库,但实际行为是不可靠的。



预先感谢!

UPDATE#2 :通过调试,我可以确认数据存储具有正确的信息,并且在查询运行时,它会回退到二级缓存 - 它具有脏信息。我认为每当数据发生变化时,我无法从缓存中逐出?

解决方案

我发现了这个问题,但它基本上,当修改 Book 对象的 List< PageContent>
字段,Hibernate会做三件事:


  1. Book PageContent

  2. 是否有许多查询重置 pageNum PageContent 对象

  3. c>字段将 Book 第二级缓存。

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


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

  2. 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:

    1. Expires the TimeStamp cache entry for both Book and PageContent
    2. Does many queries to reset the pageNum field on each PageContent object
    3. Removes the Book object from the Second Level Cache.

    This ensures that subsequent queries will search for new objects, etc. However:

    1. Hibernate fails to remove each renumbered PageContent object from the Second Level Cache

    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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆