具有复合键的 Hibernate 双向 one-to-many

Hibernate Bidirectional one-to-many with composite key

我正在尝试在两个实体之间创建双向 one-to-many 关联,其中多方具有复合键。多边的关键之一来自单边。另外,我需要有许多方面的协会所有者。下面是一个示例代码,展示了我的代码的样子。

不可拼接

Parent Class 这是一侧。我需要有协会的这边所有者。

    public class parent{

    @Id
    @Column(name = "NAME")
    private String name;

    @OneToMany(fetch=FetchType.LAZY)
    @JoinColumns({
                  @JoinColumn(name="NAME", nullable = false),
                  @JoinColumn(name="PARENT", nullable = false)})
    private Set<Child> childs;
}

Child Class 也就是多边。它的主键是 "name" 和 "parent"。 "parent"来自协会。

public class child{

    @EmbeddedId
    @AttributeOverrides({
            @AttributeOverride(name="parent", column=@Column(name="PARENT", nullable=false)),
            @AttributeOverride(name="name", column=@Column(name="NAME", nullable=false))})
    private ChildId id;

    @ManyToOne(fetch=FetchType.LAZY)
    @JoinColumns({
                   @JoinColumn(name="PARENT", nullable = false, updatable = false, insertable = false),
                   @JoinColumn(name="NAME", nullable = false, updatable = false, insertable = false)})
    private Parent parent;
}

ChildId 是嵌入的 ID。

@Embeddable
public class childId{

    @Column(name = "PARENT")
    private String parent;

    @Column(name = "NAME")
    private String name;
}

可连接

Parent Class

    public class parent{

    @Id
    @Column(name = "NAME")
    private String name;

    @OneToMany(fetch = FetchType.LAZY)
    @JoinTable(name="PARENTCHILD",
                joinColumns= {@JoinColumn(name="PNAME", referencedColumnName = "NAME", nullable = false)},
                inverseJoinColumns = {
                        @JoinColumn(name="CNAME", referencedColumnName = "NAME", nullable = false),
                        @JoinColumn(name="CPNAME", referencedColumnName = "PARENT", nullable = false)})
    private Set<Child> childs;
}

Child Class

public class child{

    @EmbeddedId
    @AttributeOverrides({
            @AttributeOverride(name="parent", column=@Column(name="PARENT", nullable=false)),
            @AttributeOverride(name="name", column=@Column(name="NAME", nullable=false))})
    private ChildId id;

    @MapsId("parent")
    @ManyToOne(fetch=FetchType.LAZY)
    @JoinTable(name="PARENTCHILD",
                inverseJoinColumns = {@JoinColumn(name="PNAME", referencedColumnName = "NAME", nullable = false)},
                joinColumns = {
                        @JoinColumn(name="CNAME", referencedColumnName = "NAME", nullable = false),
                        @JoinColumn(name="CPNAME", referencedColumnName = "PARENT", nullable = false)})
    private Parent parent;
}

问题1: 此代码不起作用。在 "without jointable" 的情况下,它会给出以下异常。

Caused by: org.hibernate.AnnotationException: A Foreign key refering com.entity.Parent from com.entity.Child has the wrong number of column. should be 1

问题2: 在 "with jointable" 的情况下,它给出以下异常:

SQLCODE=-530, SQLSTATE=-23503, SQLERRMC=PARENTCHILD.FK_PARENTCHILD_CHILD

要使用 One-To-Many 通过联接 table 的双向映射,请使用以下代码:

Parent Class

 public class parent{
        @Id
        @Column(name = "id")
        @GeneratedValue(strategy = GenerationType.IDENTITY)    
        private Long id;
        .....
        .....
        @OneToMany(cascade=CascadeType.ALL)
        @JoinTable(name="Parent_Child", joinColumns={@JoinColumn(name ="parentId", referencedColumnName ="id")},
            inverseJoinColumns={@JoinColumn(name ="childId", referencedColumnName ="id")})
        private Set<Child> children;
        .....
        .....
 }

Child Class

 public class Child{
        @Id
        @Column(name = "id")
        @GeneratedValue(strategy = GenerationType.IDENTITY)    
        private Long id;
        .....
        .....
        @OneToOne(cascade=CascadeType.ALL)
        @JoinTable(name="Parent_Child", joinColumns={@JoinColumn(name ="childId", referencedColumnName ="id")},
            inverseJoinColumns={@JoinColumn(name ="parentId", referencedColumnName ="id")})
        private Parent parent;
        .....
        .....
 }

请注意,我在 Parent class 中使用了 OneTOMany 映射 - 因为根据您的逻辑,一个 parent 可以有多个 children 和我在 Child class 中使用了 OneToOne 映射,因为一个 child 将有一个 parent(如您的要求中所述)。

希望对您有所帮助

您不需要在 Child 中单独保留 Parent 名称作为 Id,Hibernate 会为您完成。我做了一个更简单的设计。你可以通过在 @ManyToOnemappedBy = parent 中使用 mappedBy = childs 来控制关系。

@Entity
    public class Parent{

    @Id
    private String name;

    @OneToMany(fetch= FetchType.LAZY)
    private Set<Child> childs;

    public Parent(String name) {
        this.name = name;
    }
    public Parent(){}
}

@Entity
public class Child{

    @Id
    private String name;

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

Hibernate 将生成三个 tables

子 Table 具有列名称(主键),parent_name(外键) Parent Table 有一个列名(主键) Parent_child table 有两列 parent_name 和 child_name

编辑:根据 amir 的需要更改解决方案,只需添加 mappedBy 以控制关系。

@Entity
public class Child implements Serializable {

    @Id
    private String name;

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

@Entity
public class Parent{

    @Id
    private String name;

    @OneToMany(fetch= FetchType.LAZY)
    private Set<Child> childs;

    public Parent(String name) {
        this.name = name;
    }
    public Parent(){}
}

编辑 - 在子端命名列

@Id()
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="xyz")
private Parent parent;