JpaRepository合并()方法

w1e3prcc  于 2022-11-14  发布在  其他
关注(0)|答案(1)|浏览(143)

I'm rewriting a big project with SpringBoot 2.2.6 and I'm run into a problem.
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);

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.
But with SpringBoot I'm using JpaRepository and I don't think the same thing happens if I call:

jpaRepository.save(entity);

I think with this call the other fields of SubEntity with specified id will set to null!
Is it correct?
What can I solve this?
Thanks for your reply first of all!
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
}

And:

@Entity
public class Engine {

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

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];

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);

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);

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

hc2pp10m

hc2pp10m1#

你有没有给予过,还是只是猜测?
首先,您不需要采用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断定该实体不是新的,则它调用em.merge
实体是否为新实体的检查是在AbstractEntityInformation.isNew中进行的。只有当实体的id为空(或对于基元数字类型为0)时,它才得出实体为新实体的结论。
你把id从dto赋值给。如果它不为null(或者对于原语来说不为零),就没有理由相信新代码的行为会与旧代码不同。

更新问题的答案

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

参考:

有关实体是否为新实体的更多信息,请参阅here

相关问题