【问题标题】:Hibernate MANUAL flushmode behaves like AUTO休眠手动刷新模式的行为类似于自动
【发布时间】:2021-09-15 00:30:51
【问题描述】:

我正在尝试使用 HQL 更新表并希望将刷新模式设置为手动。我尝试了两种方法。

// Update user via session
em.unwrap(Session.class).createQuery("update User u set u.numRecords =:numRecords where u.id = 1")
    .setParameter("numRecords", new Random().nextInt(1234567))
    .setHibernateFlushMode(FlushMode.MANUAL)
    .executeUpdate();

// Update user via entity manager.
Query query = em
    .createQuery("update User u set u.numRecords =:numRecords where u.id = 1")
    .setParameter("numRecords", new Random().nextInt(1234567));
((QueryImpl) query).setFlushMode(FlushMode.MANUAL).executeUpdate();

我的调用者调用这两种方法如下 -

@Transactional
public void foo() {
    userRepository.updateUserViaSession();
    userRepository.clear();
}

@Transactional
public void foo2() {
    userRepository.updateUserViaEntityManager();
    userRepository.clear();
}

实体 -

@Entity
@Table(name = "users")
public class User {
    @Id
    private Long id;
    private String email;
    private int numRecords;
    private int numAllowedRecords;
}

问题是当我调用 foo() 或 foo2() 时,Hibernate 会立即刷新更新,而不是等待我显式调用 flush()。为什么会这样?

【问题讨论】:

  • 我猜@Transactional 注释强制刷新。此外,您没有显示 userRepository.clear() 方法的实现。
  • userRepository.clear() 正在调用 em.clear()。 @Transactional 只会在最后强制刷新。但在此之前我会调用 clear(),所以 flush() 应该什么都不做。但 DB 实际上正在更新。无论如何,我可以从数据库日志中看到,刷新实际上是在事务中间发生的,这很奇怪,因为它是手动的。
  • 这很奇怪,从来没有遇到过这样的问题。 . .我知道这听起来可能有点愚蠢,并且可能不适合您的用例,但是您是否尝试过直接在 Session 和 EntityManager 中将刷新模式设置为MANUAL,而不是设置为查询?同样,我知道这可能听起来有点愚蠢,可能不适合您的需求,但请尝试一下并检查是否会发生同样的问题。

标签: spring-boot hibernate


【解决方案1】:

FlushMode 不是这样工作的。

在查询上设置FlushMode 可控制是否应在 查询执行之前刷新持久性上下文。它对 when 查询执行没有影响。 JPA 总是立即执行查询。

当您不希望查询看到在当前上下文中所做的更改时,覆盖FlushMode 很有用。默认情况下,JPA 假定到目前为止所做的所有更改都应该被查询看到,因此它会在执行之前刷新上下文以确保这一点。

【讨论】:

  • 语句是否有参考——“JPA 总是立即执行查询。”?从docs.jboss.org/hibernate/orm/5.1/userguide/html_single/chapters/… 开始,它说自动刷新发生在“执行与排队实体操作重叠的 JPQL/HQL 查询之前”。这意味着 JPQL 不会总是立即执行查询,只会在重叠时执行。
  • “自动刷新发生在在执行与排队实体操作重叠的 JPQL/HQL 查询之前”。它没有说明查询何时执行,仅在刷新发生时说明
  • 谢谢。什么时候执行 jpa 查询?
  • 正如我已经说过的,查询总是立即执行。坦率地说,我不太明白为什么您可以在稍后在代码中简单地调用它们时期望它们被延迟
  • 是否有“查询总是立即执行”的参考?
猜你喜欢
  • 1970-01-01
  • 2012-12-23
  • 1970-01-01
  • 2013-02-18
  • 1970-01-01
  • 1970-01-01
  • 2020-06-25
  • 2019-11-03
  • 1970-01-01
相关资源
最近更新 更多