Cod*_*mer 0 merge jpa spring-boot
我正在重写一个大项目,SpringBoot 2.2.6但遇到了问题。
在旧的项目(纯ejb)当一个复杂的实体更新,代码生成entity从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
}
Run Code Online (Sandbox Code Playgroud)
重要的部分是与子实体相关的部分!在进行了类似旧项目调用的映射之后:
EntityManager.merge(entity);
Run Code Online (Sandbox Code Playgroud)
我认为通过合并调用,如果数据库内部存在具有指定 id 和其他字段valorized 的 SubEntity ,则其他字段保持有效并且不会设置为 null 因为它们没有在映射中声明。
但是SpringBoot我正在使用JpaRepository,如果我打电话,我认为不会发生同样的事情:
jpaRepository.save(entity);
Run Code Online (Sandbox Code Playgroud)
我认为通过此调用,具有指定 id 的 SubEntity 的其他字段将设置为 null!
这是正确的吗?
我能解决什么?
首先感谢您的回复!
你是对的,我不能做这样的事情,也不能用 EntityManager.merge() 方法!比我试图更好地解释我想要做什么:
假设我有一个复杂的实体,它有许多嵌套实体(可能有嵌套实体),如下所示:
@Entity
public class Car {
private String name;
....
....
private Engine engine; // nested entity
private Chassis chassis; // nested entity
}
Run Code Online (Sandbox Code Playgroud)
和:
@Entity
public class Engine {
private String company;
private Oil oil; // nested entity
....
}
Run Code Online (Sandbox Code Playgroud)
现在假设在数据库中我有一辆汽车,所有关系都已填充(发动机、底盘、油等),并假设我想将汽车名称从法拉利更新为菲亚特,如果我使用纯 SQL,我可以简单地编写:
update Car c set c.name = "Fiat" where c.id = [id];
Run Code Online (Sandbox Code Playgroud)
现在,如果我使用 Spring JPA,为了确保在更新实体时所有嵌套实体(及其字段)不会设置为 null,我必须执行以下操作:
Car car = carRepository.findById([id]);
car.setName("Fiat"):
carRepository.save(car);
Run Code Online (Sandbox Code Playgroud)
通过这种方式,我将更新 Car name,并且我确定所有其他实体将保持设置状态,因为它们是由 findById() 方法加载的。
我的问题和我的目标是知道是否有办法做这样的事情:
Car car = new Car();
car.setId(1); // id of Ferrari car
car.setName("Fiat");
someRepositoryOrEntityManager.saveOrUpdate(car);
Run Code Online (Sandbox Code Playgroud)
并通过 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);
}
}
Run Code Online (Sandbox Code Playgroud)
这意味着如果得出结论该实体不是新的,则JpaRepository.save调用em.merge。
检查实体是否是新的在AbstractEntityInformation.isNew. 它得出结论,只有当其 id 为空(或原始数字类型为 0)时,实体才是新的。
您从 dto 分配 id。如果它不为空(或原语非零),则没有理由相信新代码的行为方式与旧代码不同。
回答更新的问题
如果您想修改实体而不获取它,我建议使用 JPQL 或标准查询
| 归档时间: |
|
| 查看次数: |
3728 次 |
| 最近记录: |