I would like to map a many-to-many in Hibernate using a link table. I have two classes, Parent and Child class, for example:
我想使用链接表在Hibernate中映射多对多。我有两个类,父类和子类,例如:
public class Parent{
private List<Child> _children;
//...getters and setters
}
I use a link table (link_table) with three columns link_id
, parent_id
, and child_id
. The database is SQL server and id types are uniqueidentifier. So, I usually use guid for the id fields.
我使用链接表(link_table),其中包含三列link_id,parent_id和child_id。数据库是SQL服务器,id类型是uniqueidentifier。所以,我通常使用guid作为id字段。
How can you implement this using the <list />
tag if this is the correct tag to use? Do you know of any good documentation to accomplish this?
如果这是要使用的正确标记,如何使用
标记实现此目的?你知道有什么好的文件来完成这个吗?
I am currently getting a ConstraintViolationException but have not been able to find any good documentation or examples of this.
我目前正在获取ConstraintViolationException,但未能找到任何好的文档或示例。
I think a main issue is: how to specify the link_id
to be automatically generated in the link table.
我认为一个主要问题是:如何指定link_id在链接表中自动生成。
4 个解决方案
#1
I don't think that it is possible (or necessary) to add a link_id primary key to the join table. The join table will usually consist of the primary keys of the two participating tables.
我不认为可以(或必要)将link_id主键添加到连接表。连接表通常由两个参与表的主键组成。
Using XML you will need syntax like this:
使用XML你需要这样的语法:
<class name="Parent">
....
<list name="children" table="link_table">
<key column="parent_id"/>
<many-to-many column="child_id"
class="Children"/>
</list>
...
</class>
<class name="Child">
...
<list name="parents" inverse="true" table="link_table">
<key column="child_id"/>
<many-to-many column="parent_id"
class="Parent"/>
</list>
...
</class>
Although I find annotations better to use.
虽然我发现注释更好用。
#2
I do this using annotations, specifically @ManyToMany and @JoinTable:
我这样做是使用注释,特别是@ManyToMany和@JoinTable:
@Entity
public class Employer implements Serializable {
@ManyToMany(
targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,
cascade={CascadeType.PERSIST, CascadeType.MERGE}
)
@JoinTable(
name="EMPLOYER_EMPLOYEE",
joinColumns=@JoinColumn(name="EMPER_ID"),
inverseJoinColumns=@JoinColumn(name="EMPEE_ID")
)
public Collection getEmployees() {
return employees;
}
}
@Entity
public class Employee implements Serializable {
@ManyToMany(
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
mappedBy = "employees",
targetEntity = Employer.class
)
public Collection getEmployers() {
return employers;
}
}
#3
I am not sure that you can pull this off easily for an existing database with existing data. Hibernate is usually better off defining its own data schema the first time you connect...
我不确定您是否可以轻松地为具有现有数据的现有数据库提供此功能。 Hibernate通常最好在你第一次连接时定义自己的数据模式...
I've only pulled off many-to-many with annotations, but I think the hibernate documentation offers XML based examples: link text
我只使用注释来提取多对多,但我认为hibernate文档提供了基于XML的示例:链接文本
#4
I found a very good blog online which gives 2 ways to add additional fields to the many to many mapped hibernate column. Traditionally we expect the many to many mapping to give a new table will FK's of tables mapped. But there are ways to tweak that and add more fields/column to this joined table.
我在网上发现了一个非常好的博客,它提供了两种方法来为多对多映射的hibernate列添加其他字段。传统上我们期望多对多的映射给出一个新的表,FK的表映射。但是有一些方法可以调整它并为此连接表添加更多字段/列。
This joined table may contain a PK or may contain some extra fields without PK. See this blog for exact implementation See Here
此连接表可能包含PK或可能包含一些没有PK的额外字段。有关具体实施,请参阅此博客
And as per your example, you need an extra PK in the table so you declare a new table ParentChildren and declare your primary key as linkId. I am showing just the annoated parentchildren class, as annotations for many to many mapping in parent and children class can be referenced from post above.
根据您的示例,您需要在表中添加额外的PK,以便声明一个新表ParentChildren并将主键声明为linkId。我只显示了已取消的父子类,因为父类和子类中的多对多映射的注释可以从上面的帖子中引用。
@Entity
@Table(name = "parent_children")
public class ParentChildren{
@Id @GeneratedValue
private long linkId;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "parent_id")
private Parent parent;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "children_id)
private Children children;
// additional fields if you want
private boolean activated;
//getters and setters
}
}
So this will create a mapping table which has linkId as primary key and parent_id and children_id as Foreign Key. Just be clear on why you want a link_id separately as primary key and how you are going to use it.
因此,这将创建一个映射表,其中linkId作为主键,parent_id和children_id作为外键。只需清楚为什么你想单独将link_id作为主键以及如何使用它。
#1
I don't think that it is possible (or necessary) to add a link_id primary key to the join table. The join table will usually consist of the primary keys of the two participating tables.
我不认为可以(或必要)将link_id主键添加到连接表。连接表通常由两个参与表的主键组成。
Using XML you will need syntax like this:
使用XML你需要这样的语法:
<class name="Parent">
....
<list name="children" table="link_table">
<key column="parent_id"/>
<many-to-many column="child_id"
class="Children"/>
</list>
...
</class>
<class name="Child">
...
<list name="parents" inverse="true" table="link_table">
<key column="child_id"/>
<many-to-many column="parent_id"
class="Parent"/>
</list>
...
</class>
Although I find annotations better to use.
虽然我发现注释更好用。
#2
I do this using annotations, specifically @ManyToMany and @JoinTable:
我这样做是使用注释,特别是@ManyToMany和@JoinTable:
@Entity
public class Employer implements Serializable {
@ManyToMany(
targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,
cascade={CascadeType.PERSIST, CascadeType.MERGE}
)
@JoinTable(
name="EMPLOYER_EMPLOYEE",
joinColumns=@JoinColumn(name="EMPER_ID"),
inverseJoinColumns=@JoinColumn(name="EMPEE_ID")
)
public Collection getEmployees() {
return employees;
}
}
@Entity
public class Employee implements Serializable {
@ManyToMany(
cascade = {CascadeType.PERSIST, CascadeType.MERGE},
mappedBy = "employees",
targetEntity = Employer.class
)
public Collection getEmployers() {
return employers;
}
}
#3
I am not sure that you can pull this off easily for an existing database with existing data. Hibernate is usually better off defining its own data schema the first time you connect...
我不确定您是否可以轻松地为具有现有数据的现有数据库提供此功能。 Hibernate通常最好在你第一次连接时定义自己的数据模式...
I've only pulled off many-to-many with annotations, but I think the hibernate documentation offers XML based examples: link text
我只使用注释来提取多对多,但我认为hibernate文档提供了基于XML的示例:链接文本
#4
I found a very good blog online which gives 2 ways to add additional fields to the many to many mapped hibernate column. Traditionally we expect the many to many mapping to give a new table will FK's of tables mapped. But there are ways to tweak that and add more fields/column to this joined table.
我在网上发现了一个非常好的博客,它提供了两种方法来为多对多映射的hibernate列添加其他字段。传统上我们期望多对多的映射给出一个新的表,FK的表映射。但是有一些方法可以调整它并为此连接表添加更多字段/列。
This joined table may contain a PK or may contain some extra fields without PK. See this blog for exact implementation See Here
此连接表可能包含PK或可能包含一些没有PK的额外字段。有关具体实施,请参阅此博客
And as per your example, you need an extra PK in the table so you declare a new table ParentChildren and declare your primary key as linkId. I am showing just the annoated parentchildren class, as annotations for many to many mapping in parent and children class can be referenced from post above.
根据您的示例,您需要在表中添加额外的PK,以便声明一个新表ParentChildren并将主键声明为linkId。我只显示了已取消的父子类,因为父类和子类中的多对多映射的注释可以从上面的帖子中引用。
@Entity
@Table(name = "parent_children")
public class ParentChildren{
@Id @GeneratedValue
private long linkId;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "parent_id")
private Parent parent;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "children_id)
private Children children;
// additional fields if you want
private boolean activated;
//getters and setters
}
}
So this will create a mapping table which has linkId as primary key and parent_id and children_id as Foreign Key. Just be clear on why you want a link_id separately as primary key and how you are going to use it.
因此,这将创建一个映射表,其中linkId作为主键,parent_id和children_id作为外键。只需清楚为什么你想单独将link_id作为主键以及如何使用它。