【问题标题】:Hibernate AUTO flush strategy orderHibernate AUTO 刷新策略顺序
【发布时间】:2017-07-09 16:17:59
【问题描述】:

我有 2 种方法在 Hibernate 中的刷新方面表现出不同的行为。

第一个是:

    @Transactional
    public void firstMthod(int id, int status) {
        Person entity = session.get(Person.class, id);
        entity .setStatus(personStatus.registered);
        session.merge(entity);
        updatePersonAge(id,18);
    }

updatePersonAge 方法位于另一个类中,该方法的 SQL 输出如下所示:

select personel0_.ID            as ID1_119_0_,
       personel0_.status        as status2_119_0_,
       personel0_.age           as age3_119_0_,
       personel0_.CreatedBy     as CreatedBy4_119_0_,
       personel0_.UpdatedBy     as UpdatedBy5_119_0_,
       personel0_.CreatedDate   as CreatedDate6_119_0_,
       personel0_.UpdatedDate   as UpdatedDate7_119_0_,
       personel0_.Ip            as Ip8_119_0_
  from tbl_personel personel0_
 where personel0_.ID = ?
update tbl_person set status = ? where ID = ?
update tbl_person set age = ? where ID = ?

对于第二个用例,我们有以下方法:

    @Override
    @Transactional
    public void secondMethod(int id,int courseId, int status) {
        Course courseEntity=session.get(Course .class, courseId); 
        courseEntity.setCreatedDate(new Date());
         session.merge(courseEntity);
        updatePersonAge(id,18);
    }

updatePersonAge 方法为此生成以下 SQL 输出:

select course0_.ID          as ID1_120_0_,
       course0_.CreatedBy   as CreatedBy7_120_0_,
       course0_.UpdatedBy   as UpdatedBy8_120_0_,
       course0_.CreatedDate as CreatedDate9_120_0_,
       course0_.UpdatedDate as UpdatedDate10_120_0_,
       course0_.Ip          as Ip11_120_0_
  from tbl_course course0_
 where course0_.ID = ?
update tbl_course set created_date = ? where ID = ?
update tbl_person set age = ? where ID = ?

updatePersoneAge 方法是:

public int updatePersonAge(int id,int age){
        Query query = session.createQuery("update " + domainClass.getName() + " e set e.age= :age ");
                query.setParameter("age ", age);
                return query.executeUpdate();
        }

按照我的预期,第二种方法的输出应该和第一种方法的输出相同。那么为什么会有差异呢?真的很混乱。

【问题讨论】:

  • 在块事务中获取更新查询时,例如“update”命令,在执行该行之前,但我不知道为什么第二种方法的结果不是。

标签: java spring hibernate transactions flush


【解决方案1】:

首先,在已经附加到当前运行的Session 的实体上调用merge 是没有意义的。 Merge 用于附加分离实体时使用。

其次,Hibernate FetchMode.AUTOflush 只有在即将运行的查询与ActionQueue 中的实体重叠时才会触发flush。

在第一个示例中,因为您修改了Person,并且查询是针对Person 运行的,所以触发刷新是有意义的,否则,SQL 查询可能会返回陈旧的结果。

在第二种情况下,您修改了 Course 实体,但您想从 Person 中进行选择。因此,无需触发刷新。

您可以使用Query.addSyncronizedEntityName 控制此行为。

【讨论】:

    【解决方案2】:

    除了在updatePersonAge 方法中显式更新年龄之外,在每个事务中,您还隐式更新(通过获取实体并更改其中一个字段)托管实体的其他字段。

    当您合并这些更改时,PERsistence Provider 有义务在事务结束时刷新这些更改。

    这就是为什么当你改变状态时:

    Person entity = session.get(Person.class, id);
            entity .setStatus(personStatus.registered);
            session.merge(entity);
    

    Hibernate 会随着显式年龄更新而持续变化:

    update tbl_person set status = ? where ID = ?
    update tbl_person set age = ? where ID = ?
    

    第二种方法当你改变Course实体的一个字段时:

    Course courseEntity=session.get(Course .class, courseId); 
            courseEntity.setCreatedDate(new Date());
             session.merge(courseEntity);
    

    该更改与显式年龄更新一起保留:

    update tbl_course set created_date = ? where ID = ?
    update tbl_person set age = ? where ID = ?
    

    【讨论】:

      猜你喜欢
      • 2011-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多