Java Hibernate查询返回过时的数据
我有一个hibernate查询(hibernate 3),它只从数据库中读取数据。数据库由单独的应用程序更新,查询结果不反映数据库中的更改 通过一些研究,我认为它可能与Hibernate二级缓存有关(我不认为它是一级缓存,因为我总是打开一个新会话,并在完成后关闭它)Java Hibernate查询返回过时的数据,java,hibernate,caching,Java,Hibernate,Caching,我有一个hibernate查询(hibernate 3),它只从数据库中读取数据。数据库由单独的应用程序更新,查询结果不反映数据库中的更改 通过一些研究,我认为它可能与Hibernate二级缓存有关(我不认为它是一级缓存,因为我总是打开一个新会话,并在完成后关闭它) Session Session=sessionFactoryWrapper.getSession(); List result=session.createSQLQuery(flowCountSQL.List(); session.
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)会话会话=sessionFactoryWrapper.getSession()之后的代码>会话代码>强制刷新一级缓存但仍不工作
是否有其他方法获取数据库中的更改?我在如何禁用缓存方面做错了什么吗?谢谢
更新:
我通过监视数据库查询日志做了另一个实验:
第一次运行代码。检查日志。查询显示出来
等几分钟。数据已被其他应用程序更改。我通过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'
}
}