强制Hibernate查询访问数据库

时间:2021-02-23 19:13:19

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查询,例如从Person p中选择p.property,其中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?

有没有办法解决?

4 个解决方案

#1


11  

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查询,例如从Person p中选择p.property,其中p.id = 1,其中包含事务中加载的实体的ID。

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)
  • 使用session.refresh()强制重新加载您的实体(并且您将松开更改)
  • store the previous value as initially mentioned.
  • 存储最初提到的先前值。
  • invoke a service that perform a query in another transaction.
  • 调用在另一个事务中执行查询的服务。

#2


7  

The StatelessSession worked for me.

StatelessSession为我工作。

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

#3


2  

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

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

#4


1  

The only way to do this would be to run the query outside of the current transaction.

执行此操作的唯一方法是在当前事务之外运行查询。

#1


11  

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查询,例如从Person p中选择p.property,其中p.id = 1,其中包含事务中加载的实体的ID。

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)
  • 使用session.refresh()强制重新加载您的实体(并且您将松开更改)
  • store the previous value as initially mentioned.
  • 存储最初提到的先前值。
  • invoke a service that perform a query in another transaction.
  • 调用在另一个事务中执行查询的服务。

#2


7  

The StatelessSession worked for me.

StatelessSession为我工作。

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

#3


2  

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

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

#4


1  

The only way to do this would be to run the query outside of the current transaction.

执行此操作的唯一方法是在当前事务之外运行查询。