繁体   English   中英

在没有会话刷新的情况下,Hibernate标准结果会在单个事务期间更新吗?

[英]Will Hibernate criteria results update during a single transaction without session flush?

无论出于何种原因,我都有一个代码,其本质上执行以下操作:在单个事务/会话中多次加载一个实例:

@Transactional
public void fun(final String someName){
    for(int i=0; i<10; ++i) {
        SomeClass someClass = (SomeClass) session()
                    .createCriteria(SomeClass.class)
                    .add(Restrictions.eq("name", someName))
                    .uniqueResult();

        // when not found
        if(someClass == null){
           someClass = new SomeClass();
           someClass.setName(someName); // it SHOULD be found in subsequent criteria calls
       }

        process(someClass);

        session().saveOrUpdate(someClass);
        // session.flush();                     // should it be here?
    }
}

我不确定的是session().createCriteria...调用的结果在循环期间是否更改。

它是在事务中,如果我找不到实体-我会创建它(但只能创建一次)。

因此,在第二遍过程中, someClass实例将始终为非null吗?

当然,您不必调用冲洗,应该很少执行冲洗。 但是,证明某事的最佳方法是使用一个简单的演示,因此我编写了一个Spring Boot / Data示例并将其推到Github上 该代码与您的代码等效,并使用Hibernate 4.3.5:

@Transactional
public void createOrUpdateEmployee(String firstName, String lastName) {
  for (int i = 0; i < 10; i++) {
    Employee employee = repository.findByLastName(lastName);
    if (employee == null) {
      employee = new Employee(firstName, lastName);
      if (i > 0) {
        throw new IllegalStateException("This can never happen!");
      }
    }

    log.info(employee);

    repository.save(employee);
  }
}

输出为:

....350  ...EmployeeService      : Employee [id=0, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....396  ...EmployeeService      : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....401  ...EmployeeService      : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....403  ...EmployeeService      : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....405  ...EmployeeService      : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....407  ...EmployeeService      : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....410  ...EmployeeService      : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....412  ...EmployeeService      : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....427  ...EmployeeService      : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]
....429  ...EmployeeService      : Employee [id=1, firstName=Andreas, lastName=Kluth, hashCode=1686333223]

就像我期望的那样,该实体是从L1缓存中检索的(hashCode保持不变),并已自动刷新,因为已提到的文档链接指出: https : //access.redhat.com/documentation/zh-CN/JBoss_Enterprise_Web_Platform/5 /html/Hibernate_Core_Reference_Guide/objectstate-flushing.html

每次您的代码通过此处:

 SomeClass someClass = (SomeClass) session()
                    .createCriteria(SomeClass.class)
                    .add(Restrictions.eq("name", someName))
                    .uniqueResult();

someClass将为null或对数据库中注册表的引用。

(我假设.add(Restrictions.eq("name", someName))始终返回唯一的结果,否则将引发异常)

如果要创建具有不同@ids对象, @ids在此处进行process(someClass); 那就不用担心了

我通常使用flush ,当数据库动态生成id时 ,我需要该对象立即反映它(例如,一个序列ID),因此可以使用它。

但是对于您而言,我认为您在process方法中为someClass提供了不同的ids ,因此您不必担心刷新。


EDITED

Opsss ...

我没看到这条线

//应该在随后的条件调用中找到

假设这样, 您应该冲洗一下 因此,数据库将反映您的新注册表,否则,只有在整个交易结束时才能看到所有注册表。


另一件事:

如果这是真实的代码,则应执行以下操作:

SomeClass someClass = (SomeClass) session()
.createCriteria(SomeClass.class)
.add(Restrictions.eq("name", someName))
.uniqueResult();

for(int i=0; i<10; ++i) {

这样,假设您正在搜索同一对象,则无需在每次迭代时都进入数据库。 (一级缓存可以在这里提供帮助,但是如果您知道它与所获取的对象是同一对象,请将其放在循环之外)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM