在Spring Data JPA中使用OneToMany关系更新嵌套的子实体

时间:2020-09-28 03:08:08

标签: java spring-boot hibernate jpa spring-data-jpa

我目前有一个Parent实体,该实体的子代具有OneToMany映射,而子实体又具有其子代具有OneToMany映射,依此类推。总而言之,它最终变成了多个层次。我想知道什么是处理更新的最佳方法。到目前为止,这就是我所拥有的(为了简便起见,我已将一些类名重命名,并省略了getters / setter方法,因此请原谅任何错字)。

@Entity
@Table(name = "parent")
public class Parent implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @Column(name = "id")
    private Long id;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "parent_id")
    private List<Children> children = new ArrayList<>();

    public void setChildren(List<Children> children) {
        this.children.clear();
        for (Children child : children) {
            child.setParent(this);
        }
        this.children.addAll(children);
    }

    public void addChild(Children child) {
        child.setParent(this);
        this.children.add(child);
    }
   
    // additional setters and getters omitted for brevity 
@Entity
@Table(name = "children")
public class Children implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "children_id")
    private List<ChildrenOfChildren> childrenOfChildren = new ArrayList<>();

    @ManyToOne(fetch = FetchType.LAZY)
    private Parent parent;

    // setters and getters omitted for brevity
@Entity
@Table(name = "children_of_children")
public class ChildrenOfChildren implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private Long id;

    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
    @JoinColumn(name = "children_of_children_id")
    private List<ChildrenOfChildrenOfChildren> childrenOfChildrenOfChildren = new ArrayList<>();

    @ManyToOne(fetch = FetchType.LAZY)
    private Children children;

    // setters and getters omitted for brevity

...等等。我有一个JPA储存库类和一个使用该储存库类来获取我的Parent对象及其关联的子代和子代子代的服务类,等等。这符合我的预期。

我的问题是,如果给定Parent对象,我应该如何以一种优雅而有效的方式处理更新?客户会发送一个Protobuf请求,然后我将其映射到我创建的实体类。我目前正在这样做:

@Service
public class ParentService {

    private final ParentRepository parentRepository;
    private final ChildrenRepository childrenRepository;
    private final ChildrenOfChildrenRepository childrenOfChildrenRepository;
    // additional repos as needed for each level

    @Autowired
    public ParentService(ParentRepository parentRepository,
                             ChildrenRepository childrenRepository,
                             ChildrenOfChildrenRepository childrenOfChildrenRepository) {
        this.parentRepository = parentRepository;
        this.childrenRepository = childrenRepository;
        this.childrenOfChildrenRepository = childrenOfChildrenRepository;
    }

    @Transactional
    public void updateParent(ProtobufPojo pojo) {
        Parent parentEntity = parentRepository.findById(pojo.getId()).get();
        if (parentEntity == null) {
            parentEntity = new Parent();
        }

        parentEntity.setField(pojo.getField());
        parentEntity.setField2(pojo.getField2());
        parentEntity.setChildren(mapChildren(pojo.getChildrenList()));
        parentRepository.save(parentEntity );
    }

    @Transactional
    public List<Children> mapChildren(List<ChildrenPojo> childrenPojoList) {
        List<Children> childrenEntities = new ArrayList<>();
        for (ChildrenPojo pojo : childrenPojoList) {
            Children childrenEntity = childrenRepository.findById(pojo.getId()).get();
            if (childrenEntity == null) {
                childrenEntity = new Children();
            }

            childrenEntity.setField(pojo.getName());
            // continue mapping children of children, and so on
            childrenEntity.setChildrenOfChildren(mapChildrenOfChildren(pojo));
            childrenEntities.add(childrenEntity);
        }
        return childrenEntities;
    }

    @Transactional
    public List<ChildrenOfChildren> mapChildrenOfChildren(List<ChildrenOfChildrenPojo> childrenOfChildrenPojoList) {
        // repeat...
    }
}

这是解决此问题的正确方法吗?从顶级Parent那里,我实际上是在检查它是否存在,如果存在,则从客户端POJO映射其所有字段,然后继续向下至其子项,映射其字段,依此类推。我并不完全相信这是最好的方法,因为我实际上是在覆盖字段(即使它们是相同的),但是从目前为止我所看到的,这将处理更新,添加新节点以及删除节点。我想念什么吗?

任何建议将不胜感激。预先感谢!

0 个答案:

没有答案