Java 强制 Hibernate 查询访问数据库
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3700830/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Force Hibernate query to access database
提问by tobiasbayer
I have loaded an entity into my transaction and have changed a property of that entity. The transaction is not yet commited. Now I would like to get the original value of the changed property.
我已将一个实体加载到我的事务中并更改了该实体的属性。事务尚未提交。现在我想获取已更改属性的原始值。
I've tried with a HQL query like select p.property from Person p where p.id = 1
with the ID of the entity loaded in the transaction.
我尝试过使用 HQL 查询,例如select p.property from Person p where p.id = 1
使用事务中加载的实体的 ID。
I've set query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE);
before executing the query. But no success. Hibernate returns the value as set in the current transaction, not the one from the database.
我query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE);
在执行查询之前已经设置了。但没有成功。Hibernate 返回当前事务中设置的值,而不是数据库中的值。
Is there any way around this?
有没有办法解决?
采纳答案by Pascal Thivent
I have loaded an entity into my transaction and have changed a property of that entity. The transaction is not yet commited. Now I would like to get the original value of the changed property.
我已将一个实体加载到我的事务中并更改了该实体的属性。事务尚未提交。现在我想获取已更改属性的原始值。
In short: track the old value yourself.
简而言之:自己跟踪旧值。
I've tried with a HQL query like select p.property from Person p where p.id = 1 with the ID of the entity loaded in the transaction.
我尝试过使用 HQL 查询,例如 select p.property from Person p where p.id = 1 with the ID of the entity load in the transaction.
Hibernate loads a unique version of an entity into the session (the first level cache) for a given database identifier. This won't work.
Hibernate 将实体的唯一版本加载到会话(第一级缓存)中,以获取给定的数据库标识符。这行不通。
I've set query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE); before executing the query.
我已经设置了 query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE); 在执行查询之前。
This hint is used to affect the query cache(that rely on the second-level-cache), this won't affect your current "issue".
此提示用于影响查询缓存(依赖于二级缓存),这不会影响您当前的“问题”。
Is there any way around this?
有没有办法解决?
Either
任何一个
- use
session.refresh()
to force a reload of your entity (and you'll loose the changes) - store the previous value as initially mentioned.
- invoke a service that perform a query in another transaction.
- 用于
session.refresh()
强制重新加载您的实体(并且您将丢失更改) - 存储最初提到的先前值。
- 调用在另一个事务中执行查询的服务。
回答by Sebastian
This may help:
这可能有帮助:
If you want to force the query cache to refresh one of its regions (disregard any cached results it finds there) you can use org.hibernate.Query.setCacheMode(CacheMode.REFRESH). In conjunction with the region you have defined for the given query, Hibernate will selectively force the results cached in that particular region to be refreshed. This is particularly useful in cases where underlying data may have been updated via a separate process and is a far more efficient alternative to bulk eviction of the region via org.hibernate.SessionFactory.evictQueries().
如果您想强制查询缓存刷新其区域之一(忽略它在那里找到的任何缓存结果),您可以使用 org.hibernate.Query.setCacheMode(CacheMode.REFRESH)。结合您为给定查询定义的区域,Hibernate 将有选择地强制刷新缓存在该特定区域中的结果。这在底层数据可能已通过单独进程更新的情况下特别有用,并且是通过org.hibernate.SessionFactory.evictQueries()批量驱逐区域的更有效替代方法 。
(From http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html, section 20.4.2).
(来自http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html,第 20.4.2 节)。
However, is it intended to use when other process is updating the DB, and should be used with care. Your case is different. As this method occurs outside any transaction, you should be sure it does not conflict with your design. Maybe you can refactor your call flow to avoid that behavior, and retrieve the field from another source or before the modification in the cache takes place...
但是,它是否打算在其他进程正在更新数据库时使用,应谨慎使用。你的情况不同。由于此方法发生在任何事务之外,因此您应该确保它不会与您的设计发生冲突。也许您可以重构您的调用流程以避免这种行为,并从另一个来源或在缓存中的修改发生之前检索该字段......
回答by james
The only way to do this would be to run the query outside of the current transaction.
执行此操作的唯一方法是在当前事务之外运行查询。
回答by andrefaria
The StatelessSession worked for me.
StatelessSession 为我工作。
StatelessSession statelessSession = sessionFactory.openStatelessSession();
try {
return statelessSession.get(Ticket.class, ticketKey, LockMode.READ)
} finally {
statelessSession.close()
}