繁体   English   中英

DTO 到 JPA 实体与 orika 的 onetomany 双向关系

[英]DTO to JPA Entity in onetomany bidirectional relationship with orika

我正在将传入的 DTO 对象复制到具有双向 OneToMany 关系的 JPA 实体,使用 orika 库(尝试了不同的其他库,如 Dozer、SpringBeanUtils 等,并且都具有相同的效果),虽然复制工作正常但持久化实体不会更新子实体的外键. 我知道这是由于缺少与父实体的子实体同步而发生的。

但是使用 orika 或任何类似库的整个想法是避免分别复制每个实体/对象的样板代码。 所以我想知道无论如何我可以在复制过程中进行同步吗?

以下是我的实体和 DTO 类

@Entity
@Data
public class Parent
{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
@OneToMany(mappedBy=“parent”,cascade=CascadeType.ALL,OrphanRemoval=true)
private List<Child> childs;
public void addChild(Child child)
{
childs.add(child);
child.setParent(this);
}
public void removeChild(Child child)
{
childs.remove(child);
child.setParent(null);
}
}


@Entity
@Data
public class Child
{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
private Long id;
private String name;
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name=“parent_id”)
private Parent parent;
}

@Data
public class ParentDto
{
private Long id;
private String name;
private List<ChildDto> childs;
}

@Data
public class ChildDto
{
private Long id;
private String name;
}

还有奥奇亚的复制逻辑——

DefaultMapperFactory factory=new DefaultMapperFactory().Builder().build();
factory.classMap(ParentDto.class,Parent.class).byDefault().register();
Parent parentEntity=factory.getMapperFacade().map(parentDtoObject,Parent.class);
//parentEntity.getChilds().forEach(child -> child.setParent(parentEntity));
repository.save(parentEntity);

当repository.save() 完成时,子表parent_id 的foreign_key 被持久化为null 而不是实际值。 但是,如果我取消注释该行注释它工作正常,我不想这样做,因为我的实体有很多子对象并且循环会影响性能并且代码看起来也很丑陋。 有没有更好的方法来做到这一点? 或者单向 OneToMany 会起作用吗?

您可以使用在设计时考虑到这一点的Blaze-Persistence Entity-Views来做到这一点。

我创建了该库以允许在 JPA 模型和自定义接口或抽象类定义的模型之间轻松映射,例如类固醇上的 Spring Data Projections。 这个想法是您按照自己喜欢的方式定义目标结构(域模型),并通过 JPQL 表达式将属性(getter)映射到实体模型。

使用 Blaze-Persistence Entity-Views 的用例的 DTO 模型可能如下所示:

@EntityView(Parent.class)
@UpdatableEntityView
public interface ParentDto {
    @IdMapping
    Long getId();
    String getName();
    void setName(String name);
    @UpdatableMapping
    Set<ChildDto> getChilds();

    @EntityView(Child.class)
    @UpdatableEntityView
    interface ChildDto {
        @IdMapping
        Long getId();
        String getName();
        void setName(String name);
    }
}

查询是将实体视图应用于查询的问题,最简单的只是按 id 查询。

ParentDto a = entityViewManager.find(entityManager, ParentDto.class, id);

Spring Data 集成允许您几乎像 Spring Data Projections 一样使用它: https : //persistence.blazebit.com/documentation/entity-view/manual/en_US/index.html#spring-data-features

Page<ParentDto> findAll(Pageable pageable);

最好的部分是,它只会获取实际需要的状态!

保存状态也很容易:

entityViewManager.save(entityManager, parentDto);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM