Hibernate AUTO刷新策略顺序

时间:2017-02-20 11:42:55

标签: java spring hibernate transactions flush

我有两种方法在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();
        }

根据我的预期,第二种方法的输出应该与第一种方法的输出相同。为什么差异呢?这真令人困惑。

2 个答案:

答案 0 :(得分:2)

首先,在已经附加到当前正在运行的merge的实体上调用Session是没有意义的。 Merge旨在使用when you want to attach a detached entity

其次,正如我在this article中所解释的那样,如果要运行的查询与AUTO中的实体重叠,则Hibernate ActionQueue flush仅触发刷新。

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

在第二种情况下,您修改了Course实体,但又要从Person中进行选择。所以,没有必要触发冲洗。

您可以使用Query.addSyncronizedEntityName中的说明使用{ "name": "@my/my-chart", ... "peerDependencies": { "d3": "^4.0.0" } } 来控制此行为。

答案 1 :(得分:0)

除了明确地更新年龄之外,在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 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 = ?