Java Hibernate查询返回过时的数据

Java Hibernate查询返回过时的数据,java,hibernate,caching,Java,Hibernate,Caching,我有一个hibernate查询(hibernate 3),它只从数据库中读取数据。数据库由单独的应用程序更新,查询结果不反映数据库中的更改 通过一些研究,我认为它可能与Hibernate二级缓存有关(我不认为它是一级缓存,因为我总是打开一个新会话,并在完成后关闭它) Session Session=sessionFactoryWrapper.getSession(); List result=session.createSQLQuery(flowCountSQL.List(); session.

我有一个hibernate查询(hibernate 3),它只从数据库中读取数据。数据库由单独的应用程序更新,查询结果不反映数据库中的更改

通过一些研究,我认为它可能与Hibernate二级缓存有关(我不认为它是一级缓存,因为我总是打开一个新会话,并在完成后关闭它)

Session Session=sessionFactoryWrapper.getSession();
List result=session.createSQLQuery(flowCountSQL.List();
session.close();
我尝试在hibernate配置文件中禁用第二层缓存,但它不起作用:

<property name="hibernate.cache.use_second_level_cache">false</property>
<property name="hibernate.cache.use_query_cache">false</property>
<propertyname="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
false
假的
org.hibernate.cache.NoCacheProvider
我还添加了
session.setCacheMode(CacheMode.Refresh)会话强制刷新一级缓存但仍不工作

是否有其他方法获取数据库中的更改?我在如何禁用缓存方面做错了什么吗?谢谢

更新: 我通过监视数据库查询日志做了另一个实验:

  • 第一次运行代码。检查日志。查询显示出来
  • 等几分钟。数据已被其他应用程序更改。我通过MySql工作台进行了验证。为了区别于前面的查询,我添加了一个伪条件
  • 第二次运行代码。检查日志,查询就会显示出来
    这两次我都使用同一个查询,但由于数据已更改,结果应该不同,但不知何故,如果没有二级缓存和查询缓存,hibernate将始终在新会话中从数据库获取所有数据


    您可以通过启用
    org.Hibernate
    包的调试日志级别(以及
    org.Hibernate.type
    的跟踪级别,如果您想查看绑定变量),检查Hibernate到底执行了哪个查询。

    为了强制一级缓存刷新,您可以使用会话的刷新(对象)方法

    从Hibernate文档中

    从基础数据库重新读取给定实例的状态。 不建议使用它来实现长时间运行的会话 跨越许多业务任务。然而,这种方法在某些情况下是有用的 特殊情况。比如说

    • 其中,数据库触发器在插入或更新时更改对象状态
    • 在同一会话中执行直接SQL(如大规模更新)后
    • 插入Blob或Clob后
    此外,您提到添加了
    session.setCacheMode(CacheMode.Refresh)
    以强制一级缓存刷新。这将不起作用,因为CacheMode不必对一级缓存执行任何操作。再次从Hibernate文档中

    CacheMode控制会话如何与第二层交互 缓存和查询缓存


    查询所反映的更改的时间有多长?如果它在某个时间后显示更改,则可能与您获取会话的方式有关

    我不熟悉SessionFactoryWrapper类,这是您编写的自定义类吗?您是否以某种方式缓存会话对象的时间超过了必要的时间?如果是这样的话,如果已经在会话中加载了对象,那么查询将重用这些对象。这就是Hibernate保证的可重复读取语义背后的思想


    您可以在运行查询之前清除会话,然后它将返回最新的数据。

    Hibernate的内置连接池机制存在错误

    将其替换为生产质量替代品,如c3p0

    在我开始使用c3p0之前,我遇到了与返回陈旧数据完全相同的问题。

    以防它是一级缓存 你能出示你的查询吗

    请参阅以下错误:

    其他:

    Hibernates一级缓存导致的可重复查找程序问题 需要明确的是,这两个测试都成功了—完全没有逻辑性:

    userByEmail('foo@bar.com').email != 'foo@bar.com'
    
    完整测试

    @Issue('https://jira.grails.org/browse/GRAILS-11645')
    class FirstLevelCacheSpec extends IntegrationSpec {
        def sessionFactory
    
        def setup() {
            User.withNewSession {
                User user = new User(email: 'test@test.org', password: 'test-password')
                user.save(flush: true, failOnError: true)
            }
    
        }
    
        private void updateObjectInNewSession(){
            User.withNewSession {
                def u = User.findByEmail('test@test.org', [cache: false])
                u.email = 'foo@bar.com'
                u.save(flush: true, failOnError: true)
            }
        }
    
        private User userByEmail(String email){
            User.findByEmail(email, [cache: false])
        }
    
        def "test first update"() {
            when: 'changing the object in another session'
            updateObjectInNewSession()
    
            then: 'retrieving the object by changed identifier (no 2nd level cache)'
            userByEmail('foo@bar.com').email == 'foo@bar.com'
        }
    
        def "test stale object in 1st level"() {
            when: 'changing the object after pulling objects to cache by finder'
            userByEmail('test@test.org')
            updateObjectInNewSession()
    
            then: 'retrieving the object by changed identifier (no 2nd level cache)'
            userByEmail('foo@bar.com').email != 'foo@bar.com'
        }
    }
    

    嗨,我已经更新了我的帖子。我确实检查了数据库查询日志,查询命中了源代码,但不知何故它没有返回正确的结果。当您手动执行查询(通过SQL客户端)时会发生什么情况?如果我手动执行查询,我将获得最新的数据。但是,在hibernate日志中,它仍然显示错误的日志。可能是连接吗?其他一些帖子建议使用C3P0作为连接提供者…我有一个非常类似的问题。你找到了一个你忘记在这里发布的解决方案了吗?@AndrewBourgeo很抱歉,我没有找到解决方案,所以我删除了Hibernate,并使用C3P0在项目中运行。这个答案不是很有用,所以我想应该是一个评论。
    @Issue('https://jira.grails.org/browse/GRAILS-11645')
    class FirstLevelCacheSpec extends IntegrationSpec {
        def sessionFactory
    
        def setup() {
            User.withNewSession {
                User user = new User(email: 'test@test.org', password: 'test-password')
                user.save(flush: true, failOnError: true)
            }
    
        }
    
        private void updateObjectInNewSession(){
            User.withNewSession {
                def u = User.findByEmail('test@test.org', [cache: false])
                u.email = 'foo@bar.com'
                u.save(flush: true, failOnError: true)
            }
        }
    
        private User userByEmail(String email){
            User.findByEmail(email, [cache: false])
        }
    
        def "test first update"() {
            when: 'changing the object in another session'
            updateObjectInNewSession()
    
            then: 'retrieving the object by changed identifier (no 2nd level cache)'
            userByEmail('foo@bar.com').email == 'foo@bar.com'
        }
    
        def "test stale object in 1st level"() {
            when: 'changing the object after pulling objects to cache by finder'
            userByEmail('test@test.org')
            updateObjectInNewSession()
    
            then: 'retrieving the object by changed identifier (no 2nd level cache)'
            userByEmail('foo@bar.com').email != 'foo@bar.com'
        }
    }