Java 在Spring Data JPA中更新具有一对多关系的嵌套子实体

Java 在Spring Data JPA中更新具有一对多关系的嵌套子实体,java,spring-boot,hibernate,jpa,spring-data-jpa,Java,Spring Boot,Hibernate,Jpa,Spring Data Jpa,我现在有一个父实体,它与子实体有一个OneToMany映射,而子实体又与子实体有自己的OneToMany映射,依此类推。总的来说,它最终变成了几个层次的深度。我想知道处理更新的最佳方式是什么。以下是我到目前为止所做的(为了简洁起见,我重命名了一些类名并省略了getter/setter,所以请原谅任何拼写错误) @实体 @表(name=“parent”) 公共类父级实现可序列化{ 私有静态最终长serialVersionUID=1L; @身份证 @列(name=“id”) 私人长id; @OneT

我现在有一个父实体,它与子实体有一个OneToMany映射,而子实体又与子实体有自己的OneToMany映射,依此类推。总的来说,它最终变成了几个层次的深度。我想知道处理更新的最佳方式是什么。以下是我到目前为止所做的(为了简洁起见,我重命名了一些类名并省略了getter/setter,所以请原谅任何拼写错误)

@实体
@表(name=“parent”)
公共类父级实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@列(name=“id”)
私人长id;
@OneToMany(fetch=FetchType.LAZY,cascade=CascadeType.ALL,orphan=true)
@JoinColumn(name=“parent\u id”)
private List children=new ArrayList();
公共子项(列出子项){
这个.children.clear();
适用于(儿童:儿童){
child.setParent(this);
}
this.children.addAll(children);
}
公共无效添加子对象(子对象){
child.setParent(this);
this.children.add(child);
}
//为简洁起见,省略了其他setter和getter
@实体
@表(name=“children”)
公共类子类实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
@列(name=“id”)
私人长id;
@OneToMany(cascade=CascadeType.ALL,orphan=true)
@JoinColumn(name=“children\u id”)
private List childrenOfChildren=new ArrayList();
@manytone(fetch=FetchType.LAZY)
私人家长;
//为简洁起见,省略了setter和getter
@实体
@表(name=“子项中的子项”)
公共类ChildrenOfChildren实现可序列化{
私有静态最终长serialVersionUID=1L;
@身份证
@GeneratedValue(策略=GenerationType.IDENTITY)
@列(name=“id”)
私人长id;
@OneToMany(cascade=CascadeType.ALL,orphan=true)
@JoinColumn(name=“children\u of\u children\u id”)
private List childrenofchildren=new ArrayList();
@manytone(fetch=FetchType.LAZY)
私人儿童;
//为简洁起见,省略了setter和getter
…等等。我有一个JPA repository类和一个服务类,它使用repository类来获取父对象及其关联的子对象和子对象的子对象,等等。这正如我所期望的那样工作

我的问题是,如果给定父对象,我应该如何以优雅高效的方式处理更新?客户端将发送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...
    }
}

@服务
公共班级家长服务{
私有最终父存储库父存储库;
私有最终儿童存储库儿童存储库;
私有最终儿童存储库儿童存储库儿童存储库;
//每一级别所需的额外回购协议
@自动连线
公共ParentService(ParentRepository ParentRepository,
儿童知识库儿童知识库,
ChildrenofChildren存储库ChildrenofChildren存储库){
this.parentRepository=parentRepository;
this.childrenRepository=childrenRepository;
this.childrenOfChildrenRepository=childrenOfChildrenRepository;
}
@交易的
公共无效更新租金(ProtobufPojo pojo){
父parentEntity=parentRepository.findById(pojo.getId()).get();
if(parentEntity==null){
parentEntity=新父级();
}
setField(pojo.getField());
setField2(pojo.getField2());
setChildren(mapChildren(pojo.getChildrenList());
parentRepository.save(parentEntity);
}
@交易的
公共列表映射儿童(列表儿童POJOLIST){
List childrenenties=new ArrayList();
for(ChildrenPojo pojo:childrenPojoList){
childrenEntity=childrenRepository.findById(pojo.getId()).get();
if(childrenEntity==null){
childrenEntity=新子女();
}
setField(pojo.getName());
//继续映射子对象的子对象,等等
setChildrenOfChildren(mapChildrenOfChildren(pojo));
添加(childrenEntity);
}
返回儿童实体;
}
@交易的
公共列表映射childrenofchildren(列表childrenOfChildrenPojoList){
//重复。。。
}
}
这是正确的方法吗?从顶层父级开始,我基本上检查它是否存在,如果存在,则从客户端POJO映射所有字段,然后继续向下映射到其子级,映射其字段,等等。我不完全相信这是最好的方法,因为我基本上覆盖了字段(即使它们是相同的),但从我目前看到的情况来看,这将处理更新、添加新节点和删除节点。我是否遗漏了什么

任何建议都将不胜感激。提前感谢

@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
@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...
    }
}