2010-09-13 72 views
10

我已经将实体加载到我的事务中并更改了该实体的属性。该交易尚未提交。现在我想获得更改属性的原始值。强制Hibernate查询访问数据库

我试着用一个HQL查询,如select p.property from Person p where p.id = 1以及事务中加载的实体的ID。

我在执行查询之前设置了query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE);。但没有成功。 Hibernate返回当前事务中设置的值,而不是数据库中的值。

有没有办法解决这个问题?

+0

难道你最终的问题是,Hibernate抱怨两次会话中的同一实体吗?听起来你可能想重新审视实现。 – 2010-09-14 03:16:48

回答

11

我已经加载了一个实体到我的交易中并且已经改变了该实体的一个属性。该交易尚未提交。现在我想获得更改属性的原始值。

总之:自己追踪旧价值。

我已经尝试过使用HQL查询,如从Person p中选择p.property,其中p.id = 1与事务中加载的实体的ID一起使用。

Hibernate将一个实体的唯一版本加载到给定数据库标识符的会话(第一级缓存)中。这不起作用。

我已经设置了query.setHint(“org.hibernate.cacheMode”,CacheMode.IGNORE);在执行查询之前。

这个提示是用来影响查询缓存(依赖于二级高速缓存),这会不会影响你现在的“问题”。

有没有办法解决这个问题?

要么

  • 使用session.refresh()强迫你的实体的重载(你会松散的变化)
  • 店作为开头提到的前值。
  • 调用在另一个事务中执行查询的服务。
2

这可能会帮助:

如果要强制查询缓存 刷新其地区 之一(忽略任何缓存的结果发现 有),可以使用 为org.hibernate.Query .setCacheMode(CacheMode.REFRESH)。 结合您为给定查询定义的区域, Hibernate将有选择地强制在该特定 区域中缓存的 结果被刷新。这在 底层数据可能已被通过一个单独的过程更新 例 特别有用,并且是经由 org.hibernate.SessionFactory.evictQueries远 更有效的替代区域的散装 驱逐()。

(从http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html,第20.4.2节)。

但是,是否打算在其他进程更新数据库时使用,并且应谨慎使用。 你的情况是不同的。由于此方法发生在任何事务之外,因此您应确保它不与您的设计冲突。也许你可以重构你的呼叫流程,以避免这种行为,并从其他来源检索字段或缓存中的修改发生之前...

+0

回顾我的回答我发现它没有完全解决您的问题。即使您完全禁用二级缓存,您的实体数据可能会进入一级缓存(会话)。为此,您应该刷新或驱逐对象...但是您应该重新输入您想要在事务提交中保存的字段。 – Sebastian 2010-09-13 13:47:06

1

要做到这一点的唯一方法是运行查询以外的当前交易。

7

StatelessSession为我工作。

StatelessSession statelessSession = sessionFactory.openStatelessSession(); 
try { 
    return statelessSession.get(Ticket.class, ticketKey, LockMode.READ) 
} finally { 
    statelessSession.close() 
}