Java Hibernate条件结果是否会在单个事务期间更新而不刷新会话?

Java Hibernate条件结果是否会在单个事务期间更新而不刷新会话?,java,spring,hibernate,persistence,Java,Spring,Hibernate,Persistence,无论出于何种原因,我有一段代码,其基本功能如下:它在单个事务/会话中加载一个实例几次: @Transactional public void fun(final String someName){ for(int i=0; i<10; ++i) { SomeClass someClass = (SomeClass) session() .createCriteria(SomeClass.class)

无论出于何种原因,我有一段代码,其基本功能如下:它在单个事务/会话中加载一个实例几次:

@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?
    }
}
@Transactional
public void fun(最后一个字符串someName){

对于(int i=0;i每次代码通过此处时:

 SomeClass someClass = (SomeClass) session()
                    .createCriteria(SomeClass.class)
                    .add(Restrictions.eq("name", someName))
                    .uniqueResult();
someClass
将为空或引用数据库中的注册表

(我假设
.add(Restrictions.eq(“name”,someName))
总是返回唯一的结果,否则它将抛出异常)

如果您在这里创建的对象具有不同的
@id
进程(someClass);
,那么您不必担心

当数据库动态生成id时,我通常使用刷新,我现在需要对象反映它(例如,序列id),这样我就可以使用它了

但是在您的情况下,我认为您在
过程
方法中为
someClass
提供了不同的
id
,因此您不必担心刷新


已编辑

Opsss

我没看到这条线

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

假设这样,您应该刷新。这样数据库将反映您的新注册表,否则,只有在整个事务结束时才能看到所有注册表


另一件事:

如果这是真正的代码,您应该执行以下操作:

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

for(int i=0; i<10; ++i) {
SomeClass SomeClass=(SomeClass)会话()
.createCriteria(SomeClass.class)
.add(Restrictions.eq(“name”,someName))
.uniqueResult();

对于(int i=0;i当然,您不必调用flush,您应该很少执行flush。但是,最好的证明方法是使用一个简单的演示,因此我编写了一个Spring引导/数据示例并将其推送到。代码与您的代码相同,并使用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);
  }
}

正如我预期的那样,实体是从一级缓存中检索的(hashCode保持不变)自动刷新,正如前面提到的文档链接所指出的:

没有更多的代码,我们只能猜测,
flush
可能是为了防止OOM,可能
someName
被更改为
过程的副作用,而您正在创建10个新实体……也许这只是您的一个坏例子,您不应该这样做t写入重试。当
someName
不是
final
成员并且在某个地方更改时,您的查询结果很可能会更改。@Andreas我更新了代码;假设
someName
是final。假设这就是全部内容-事务在单个
SomeClass
上运行,但会多次加载/保存它(因为设计模式-责任链/装饰师/类似的东西…)然后,即使您没有调用flush,只要您在同一会话中,条件也会从一级缓存中检索实体。无需调用flush。@Andreas谢谢。但您所说的与我在下面所写的完全相反。您能面对吗?我想接受一个正确的答案;-)谢谢。即使从同一事务中的条件加载它,我也应该刷新它?一级缓存呢?好吧,循环中实体的加载是这个问题的本质;-)所以,问题是:如果对对象进行了保存,它是否已经添加到一级缓存中,并且同一事务可以使用uniqueResult()找到它?是的,有点。如果条件相同(或不同条件的顺序),那么在事务结束(提交)刷新到DB后,将找到相同的实例(具有上次迭代后的状态).对吗?是的。很好。就是这样。我唯一的疑问是:您没有找到实体。因此创建了一个新实体,您保存但不刷新。下一个hibernate调用会找到您刚才创建的实体吗?我不确定。谢谢。这里还有一个重要部分是一个好的equals哈希代码,对吗?或者,Java的默认实现(身份)工作?@NaariomMet这在很大程度上取决于您的需要,我经常使用默认的hashCode/equals,如果需要的话,在业务密钥上实现一个解决方案。有更复杂的尝试来解决这个问题,例如通过特殊的注释和反射等@Andreas好的,我不需要在
SomeClass
中使用自定义的hashCode/equals。但是默认值会实现吗。请给出您在回答中描述的行为?即,不需要刷新,因为(…)@NaariomMet Yes此行为有效,即使您不实现hashCode/equals,您也可以在github上找到整个示例:使用的实体。
....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]