JpaRepository merge()方法 [英] JpaRepository merge() method
问题描述
我正在用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屋!