简体   繁体   English

JAVA Hibernate合并正在更新而不是合并

[英]JAVA Hibernate merge is updating and not merging

When I use merge I expect that hibernate will copy not null values to a persisted entity and update the database. 当我使用merge时,我希望休眠将不会将非null值复制到持久化的实体并更新数据库。 So in the bellow use-case, I expect that the merge will keep lastName with the value Last_0 and change firstName to the value First_1 . 因此,在下面的用例中,我希望合并将保持lastName的值为Last_0并将firstName更改为值First_1

but actually, hibernate is just updating, meaning that lastName become null after the code execute 但是实际上,休眠只是在更新,这意味着在代码执行后, lastName变为null

    @Transactional
    public void create()  {
        SomeEntity create = new SomeEntity();
        create.setFirstName("First_0");
        create.setLastName("Last_0");
        this.getSession().save(create);
        //now in the database id:1, firstName:First_0, lastName:Last_0
   }


   @Transactional
    public void merge()  {
        SomeEntity merge = new SomeEntity();
        merge.setId(1);
        merge.setFirstName("First_1");
        this.getSession().merge(merge);
         // now in the database id:1, firstName:First_1, lastName:null
    }
    create();
    merge();

I expect lastName to be with the value of Last_0 since it is merging. 我希望lastName具有Last_0的值,因为它正在合并。 but it is null. 但它为空。

Thanks 谢谢

You are confused about how Hibernate's merge() is implemented in practice. 您对在实践中如何实现Hibernate的merge()感到困惑。 merge() is implemented under the hood in this case via a SQL UPDATE , meaning something like the following: 在这种情况下, merge()是通过SQL UPDATE ,其含义类似于以下内容:

UPDATE some_entity
SET
    firstName = 'First_1',
    lastName = NULL
WHERE
    id = 1;

That is, it will overwrite all the field values with whatever your detached entity happens to have. 也就是说,它将使用您的分离实体碰巧拥有的任何内容覆盖所有字段值。 Note that if no record with this primary key id=1 existed, then Hibernate would have done an INSERT , not an update. 请注意,如果不存在具有此主键id=1记录,则Hibernate将INSERT ,而不是进行更新。

If you wanted to start off with the original values for the entity, then you should have used a get: 如果要开始使用实体的原始值,则应该使用get:

SomeEntity merge = (SomeEntity) this.getSession().get(SomeEntity.class, 1);
merge.setFirstName("First_1");
this.getSession().merge(merge);

Now the original values will "stick," except for the first name, which was overwritten to something else. 现在,原始名称将“粘贴”,除了名字(被覆盖其他名称)之外。

If you want hibernate to only save part of fields and not all of them use @DynamicUpdate 如果您希望休眠仅保存部分字段,而并非所有字段都使用@DynamicUpdate

Example here: https://www.baeldung.com/spring-data-jpa-dynamicupdate 此处的示例: https : //www.baeldung.com/spring-data-jpa-dynamicupdate

As posted inside: 如里面所贴:

Actually, when we use @DynamicUpdate on an entity, Hibernate does not use the cached SQL statement for the update. 实际上,当我们在实体上使用@DynamicUpdate时,Hibernate不会将缓存的SQL语句用于更新。 Instead, it will generate a SQL statement each time we update the entity. 相反,每次我们更新实体时,它将生成一条SQL语句。 This generated SQL includes only the changed columns. 此生成的SQL仅包含已更改的列。

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

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