Hibernate具有复合键的双向一对多

时间:2015-11-09 23:49:30

标签: java hibernate jpa hibernate-mapping hibernate-annotations

我正在尝试在两个实体之间创建双向一对多关联,其中多方具有复合键。许多方面的关键之一来自一方。此外,我需要让很多方面成为协会的所有者。下面是一个示例代码,显示了我的代码。

没有可加入

父类是一方。我需要这个协会的这一方所有者。

    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;
}

多方的儿童班。它的主键是“name”和“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;
}

使用Jointable

父类

    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;
}

儿童班

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 : 此代码不起作用。如果是“不加入”,则会给出以下异常。

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

2 个答案:

答案 0 :(得分:0)

要使用连接表使用一对多双向映射,请使用以下代码:

  

父类

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

儿童班

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

请注意,我在OneTOMany类中使用了Parent映射 - 因为根据您的逻辑,父级可以有多个子级,并且我在OneToOne类中使用了Child映射因为一个孩子将有一个父母(如你的要求中所述)。

希望这有帮助

答案 1 :(得分:0)

您不需要在Child中单独保留Parent name作为Id,Hibernate将为您执行此操作。我做了一个更简单的设计。你可以使用@ManyToOnemappedBy = parent中的@ManyToOne使用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将生成三个表

具有列名称(主键),parent_name(外键)的子表 具有一个列名称的父表(主键) Parent_child表,包含两列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;