克隆 JPA 实体,其中孩子有多个父母

时间:2021-07-20 08:18:08

标签: java hibernate jpa entity relationship

我有一个“有趣”的实体结构,但我一直在尝试克隆它们。我基本上有一个我正在克隆的超级父母。让我们称这个类为 Document。一个文档至少有一个 Function 和一个 Component。现在这部分不是问题,它们是 @OneToMany@ManyToOne,我可以很好地克隆它们。但是现在有第三个类同时属于 FunctionComponent - 我们称之为 Interaction。按照设计,这是 FunctionComponent 的一部分,因为它描述了两者在交互时所做的事情。

现在在正常流程中会有一个创建顺序,首先创建一个 Document,然后自动创建至少一个 ComponentFunction。之后可以创建 Interactions。您可以将其想象成一个矩阵,其中 Interaction 描述了一个 Component 如何与一个 Function 交互。一般而言,ComponentFunction 不相关,可以独立存在,但至少每个中的一个将始终存在,因此矩阵存在。

现在的问题是克隆整个文档。克隆所有嵌套实体时,必须克隆并保持它们的关系。但是,在克隆时不知道 ID(因为它们必须取消设置或创建新实体),所以我不确定如何在此处防止重复。

如何克隆整个 Document 及其与新 ID 的子关系并保持所有关系完好无损?我知道如果所有关系都处于“线性”结构中,这很容易,但多个父级似乎很困难。

为了清楚起见,这是一张图表:

ERD

Document.java

@Table(name = "document")
@Entity
public class Document {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @OneToMany(mappedBy = "document", cascade = CascadeType.ALL)
    private List<Component> components = new ArrayList<>();

    @OneToMany(mappedBy = "document", cascade = CascadeType.ALL)
    private List<Function> functions = new ArrayList<>();

}

Component.java

@Table(name = "component")
@Entity
public class Component {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @ManyToOne
    private Document document;

    @OneToMany(mappedBy = "component", cascade = CascadeType.ALL)
    private List<Interaction> interactions;

}

Function.java

@Table(name = "function")
@Entity
public class Function {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @ManyToOne
    private Document document;

    @OneToMany(mappedBy = "function", cascade = CascadeType.ALL)
    private List<Interaction> interactions;

}

Interaction.java

@Table(name = "interaction")
@Entity
public class Interaction {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @ManyToOne
    private Function function;

    @ManyToOne
    private Component component;

}

1 个答案:

答案 0 :(得分:0)

对于复制图形,通常必须构建从源到目标的身份映射,并在复制之前进行查询。像这样:

interface CustomClonable {
  Object clone(Map<Object, Object> mapping);
}

public static <T extends CustomClonable> T clone(T original, Map<Object, Object> mapping) {
  Object copy = mapping.get(original);
  if (copy == null) {
    copy = original.clone(mapping);
    mapping.put(original, copy);
  }
  return (T) copy;
}

您的所有类型都实现该接口并克隆自己,为嵌套对象调用静态克隆方法。