具有复合键的 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 会为您完成。我做了一个更简单的设计。你可以通过在 @ManyToOne
或 mappedBy = 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;
我正在尝试在两个实体之间创建双向 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 会为您完成。我做了一个更简单的设计。你可以通过在 @ManyToOne
或 mappedBy = 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;