JpaRepository merge() 方法

2024-06-23

我正在重写一个大项目SpringBoot 2.2.6我遇到了问题。

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

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
}

重要的部分是与子实体相关的部分!进行了旧项目调用的映射后:

EntityManager.merge(entity);

我认为通过合并调用,如果数据库内部存在具有指定 id 的子实体并且其他领域也受到重视,其他字段仍然有效并且不会设置为 null,因为它们未在映射中声明。

但与SpringBoot我在用着JpaRepository我认为如果我打电话的话不会发生同样的事情:

jpaRepository.save(entity);

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

这是对的吗?

我能解决这个问题吗?


首先感谢您的回复!

你是对的,我不能做类似的事情,也不能使用 EntityManager.merge() 方法!比我尝试更好地解释我想做的事情:

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

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

And:

@Entity
public class Engine {

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

现在假设在数据库中我有一辆汽车,填充了所有关系(发动机、底盘、油等..),并且假设我想将汽车名称从 Ferrari 更新为 Fiat,如果我使用纯 SQL,我可以简单地编写:

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

现在,如果我使用 Spring JPA,为了确保在更新实体时所有嵌套实体(及其字段)不会设置为 null,我必须执行以下操作:

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

这样我将更新汽车名称,并且我确信所有其他实体将保持设置状态,因为它们是通过 findById() 方法加载的。

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

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

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


您尝试过还是只是猜测?

首先,您不需要拥抱 Spring 数据存储库。如果 EntityManager 对迁移过程有帮助,您可以注入它。

其次,看执行情况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 calls em.merge如果得出结论该实体不是新的。

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

您从 dto 分配 id。如果它不为空(或原语为非零),则没有理由相信新代码的行为方式将与旧代码不同。

回答更新的问题

如果您想修改实体而不获取它,我建议使用 JPQL 或条件查询

参考:

有关实体是否新的更多信息,可以找到here https://thorben-janssen.com/spring-data-jpa-state-detection/.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JpaRepository merge() 方法 的相关文章

随机推荐