JpaRepository merge()方法 [英] JpaRepository merge() method

查看:385
本文介绍了JpaRepository merge()方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用SpringBoot 2.2.6重写一个大项目,但遇到了问题.

I'm rewriting a big project with SpringBoot 2.2.6 and I'm run into a problem.

在旧项目(纯ejb)中,当更新复杂实体时,代码从DTO's构建entity,如下所示:

In the old project (pure ejb) when a complex entity is updated, the code build entity from DTO's as follows:

public Entity dtoToEntity(DTO dto) {
  Entity entity = new Entity();
  entity.setId(dto.getID());
  // ecc...
  // ecc...
  entity.setSubEntity(dto.getSubEntity() != null ? new SubEntity(dto.getSubEntity().getId() : null);
  // and so on
}

重要的部分是与实体有关的部分!像这样的映射完成后,旧项目将调用:

The important section is that related to subentity! After made a mapping like that the old project calls:

EntityManager.merge(entity);

我认为通过合并调用,如果数据库内部存在一个具有指定id的SubEntity,并且其他字段为有效价,则其他字段保持有效,并且未设置为null,因为未在其中声明映射.

I think that with merge call, if inside the database exists a SubEntity with specified id and other fields valorized, the other fields remain valid and are not set to null because they aren't declared in mapping.

但是使用SpringBoot时,我使用的是JpaRepository,如果我打电话给我,我认为不会发生相同的事情:

But with SpringBoot I'm using JpaRepository and I don't think the same thing happens if I call:

jpaRepository.save(entity);

我认为通过此调用,具有指定ID的SubEntity的其他字段将设置为null!

I think with this call the other fields of SubEntity with specified id will set to null!

对吗?

我该怎么解决?

首先感谢您的答复!

是的,我无法使用EntityManager.merge()方法执行类似操作!比我尝试更好地解释我想做什么:

You are right, I can't do something like that nor with EntityManager.merge() method! Than I try to explain better what I want to do:

假设我有一个复杂的实体,它具有许多嵌套实体(可能具有嵌套实体),如下所示:

Suppose I have a complex Entity, which has many nested Entities (which may have nested entities) as follows:

  @Entity
  public class Car {
     private String name;
     ....
     ....
     private Engine engine; // nested entity
     private Chassis chassis; // nested entity
}

并且:

@Entity
public class Engine {

  private String company;
  private Oil oil; // nested entity
  ....
}

现在假设数据库中有一辆汽车,并且所有关系都已填充(引擎,底盘,机油等),并且如果我使用纯SQL,我想将Car的名称从法拉利更新为菲亚特,我可以简单地编写:

Now suppose in the database I have a Car, with all relationship filled (Engine, Chassis, Oil ecc..) and suppose I want to update the Car name from Ferrari to Fiat, if I use pure SQL I can simply write:

update Car c set c.name = "Fiat" where c.id = [id];

现在,如果我使用Spring JPA,要确保在更新实体时所有嵌套实体(及其字段)都未设置为null,我必须这样做:

Now if I use Spring JPA, to ensure that all nested entity (and their field) are not setting to null when I update my entity I have to do:

Car car = carRepository.findById([id]);
car.setName("Fiat"):
carRepository.save(car);

这样,我将更新Car名称,并确保所有其他实体将保持设置状态,因为它们是由findById()方法加载的.

This way I will update Car name and I'm sure that all other entities will remain set because are loaded by findById() method.

我的问题和目标是要知道是否有办法做这样的事情:

My question and my goal is to know if is there a way to do something like that:

Car car = new Car();
car.setId(1); // id of Ferrari car
car.setName("Fiat");
someRepositoryOrEntityManager.saveOrUpdate(car);

并保留所有其他字段和关系,而无需通过find方法加载所有这些字段和关系(可能由于性能原因).

And preserve all other field and relation without load all of these by the find method (maybe due to a performance reasons).

推荐答案

您尝试过还是只是猜测?

Did you give it a try or it is just guesswork?

首先,您不需要使用spring数据存储库.如果它有助于迁移过程,则可以注入EntityManager.

First of all, you don't need to embrace spring data repositories. You can inject EntityManager if it helps in the migration process.

第二,看一下SimpleJpaRepository.save

@Transactional
public <S extends T> S save(S entity) {

    if (entityInformation.isNew(entity)) {
        em.persist(entity);
        return entity;
    } else {
        return em.merge(entity);
    }
}

这意味着JpaRepository.save如果得出结论该实体不是新实体,则会调用em.merge.

This means that JpaRepository.save calls em.merge if it concludes that the entity is not new.

AbstractEntityInformation.isNew中检查该实体是否为新实体.得出的结论是,仅当实体的id为null(对于原始数字类型为0)时,该实体才是新实体.

The check if the entity is new is in AbstractEntityInformation.isNew. It concludes that the entity is new only if its id is null (or 0 for primitive numerical types).

您可以从dto中分配ID.如果它不为null(或者对于原语而言不为零),则没有理由相信新代码的行为将不同于旧代码.

You assign the id from the dto. If it is not null (or non-zero for primitives), there is no reason to believe that the new code will behave in a different way than the old one.

回答更新的问题

如果您想在不获取实体的情况下修改其实体,建议您使用JPQL或条件查询

If you want to modify an entity without fetching it, I would suggest JPQL or criteria query

这篇关于JpaRepository merge()方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆