JPA:映射 ManyToMany 关系与附加 属性
JPA: Mapping ManyToMany relationship with additional property
我在 Employee
和 SkillSet
table 之间有多对多关系,每个关系都有额外的列 numberOfYears
employeeId skillSetId numberOfYears
10 101 2
我是 JPA 的新手,无法定义具有关系的实体。我应该为 Employee_SkillSet
table 定义一个新实体 class 吗?或者我可以在 Employee
和 SkillSet
class 中定义多对多关系吗?我在哪里指定 numberOfYears
列?
编辑:似乎重复,但我明确要求使用 @IdClass
,其中一个实体是 @MappedSuperclass
,因此必须同时定义 ID 实例和引用的实体对象。
由于元组 (Employee, SkillSet) 需要一个附加字段,因此您必须创建另一个实体。
@Entity
public class Employee implements Serializable {
private @Id Long id;
@OneToMany(mappedBy="employee")
private List<EmployeeSkillSet> skillSets;
}
@Entity
public class SkillSet implements Serializable {
private @Id Long id;
}
@Entity
public class EmployeeSkillSet implements Serializable {
private @Id Long id;
private @ManyToOne Employee employee;
private @ManyToOne SkillSet skillSet;
private @Basic int numberOfYears;
}
当然你可以选择使用 @IdClass
使 ("employee", "skillSet") 成为 EmployeeSkillSet
的主键,如下所示:
@Entity @IdClass(EmployeeSkillSet.Key.class)
public class EmployeeSkillSet implements Serializable {
private @Id @ManyToOne Employee employee;
private @Id @ManyToOne SkillSet skillSet;
private @Basic int numberOfYears;
public static class Key implements Serializable {
private Long employee; // plus getter+setter
private Long skillSet; // plus getter+setter
// plus hashCode, equals
}
}
尽管出于性能原因,您可以使用 @ManyToMany 批注更好,但定义两个多对一关系以便为多对多关系建模。
你需要4个神器,有
- 员工实体
- 技能组合实体
- EmployeeSkillSet Relation实体(这里可以指定numberOfYears列)
- EmployeeSkillSetPK(EmployeeSkillSet 关系实体的主键)
代码应该是这样的
员工
package <your_package>;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Entity
@Table(name="EMPLOYEE")
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="EMPLOYEEID")
private int id;
// Rest of columns and getter and setters for all
}
技能组合
package <your_package>;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Entity
@Table(name="SKILLSET")
public class SkillSet implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="SKILLSETID")
private int id;
// Rest of columns and getter and setters for all
}
EmployeeSkillSetPK
/**
*
*/
package <your_package>;
import java.io.Serializable;
import javax.persistence.Embeddable;
/**
*
*/
@Embeddable
public class EmployeeSkillSetPK implements Serializable {
@ManyToOne
private Employee emp;
@ManyToOne
private SkillSet sk;
/**
* @return the employee
*/
public Employee getEmployee() {
return emp;
}
/**
* @param employee the employee to set
*/
public void setEmployee(Employee employee) {
this.employee = employee;
}
/**
* @return the sk
*/
public SkillSet getSkillSet() {
return sk;
}
/**
* @param sk the sk to set
*/
public void setSkillSet(SkillSet sk) {
this.sk = sk;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EmployeeSkillSetPK that = (EmployeeSkillSetPK) o;
if (employee != null ? !employee.equals(that.employee) : that.employee != null) {
return false;
}
if (sk != null ? !sk.equals(that.sk) : that.sk != null) {
return false;
}
return true;
}
public int hashCode() {
int result;
result = (employee != null ? employee.hashCode() : 0);
result = 31 * result + (sk != null ? sk.hashCode() : 0);
return result;
}
}
EmployeeSkillSet
/**
*
*/
package <your_package>;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
*
*/
@Entity
@Table(name="EMPLOYEESKILLSET")
@AssociationOverrides({ @AssociationOverride(name = "pk.employee", joinColumns = @JoinColumn(name = "EMPLOYEEID")),
@AssociationOverride(name = "pk.sk", joinColumns = @JoinColumn(name = "SKILLSETID")) })
public class EmployeeSkillSet implements Serializable {
@EmbeddedId
private EmployeeSkillSetPK pk = new EmployeeSkillSetPK();
@Column
private Integer numberOfYears;
@Transient
public Employee getEmployee() {
return pk.getEmployee();
}
public void setEmployee(Employee employee) {
pk.setEmployee(employee);
}
@Transient
public SkillSet getSkillSet() {
return pk.getSkillSet();
}
public void setSkillSet(SkillSet sk) {
pk.setSkillSet(sk);
}
public Integer getNumbersOfYears() {
return numberOfYears;
}
public void setNumbersOfYears(Integer numberOfYears) {
this.numberOfYears = numberOfYears;
}
}
这是针对 JPA 1.0 的,我现在无法测试代码,但它应该可以工作。
请注意,table 和列名是我自己写的。随意改编。
我在 Employee
和 SkillSet
table 之间有多对多关系,每个关系都有额外的列 numberOfYears
employeeId skillSetId numberOfYears
10 101 2
我是 JPA 的新手,无法定义具有关系的实体。我应该为 Employee_SkillSet
table 定义一个新实体 class 吗?或者我可以在 Employee
和 SkillSet
class 中定义多对多关系吗?我在哪里指定 numberOfYears
列?
编辑:似乎重复,但我明确要求使用 @IdClass
,其中一个实体是 @MappedSuperclass
,因此必须同时定义 ID 实例和引用的实体对象。
由于元组 (Employee, SkillSet) 需要一个附加字段,因此您必须创建另一个实体。
@Entity
public class Employee implements Serializable {
private @Id Long id;
@OneToMany(mappedBy="employee")
private List<EmployeeSkillSet> skillSets;
}
@Entity
public class SkillSet implements Serializable {
private @Id Long id;
}
@Entity
public class EmployeeSkillSet implements Serializable {
private @Id Long id;
private @ManyToOne Employee employee;
private @ManyToOne SkillSet skillSet;
private @Basic int numberOfYears;
}
当然你可以选择使用 @IdClass
使 ("employee", "skillSet") 成为 EmployeeSkillSet
的主键,如下所示:
@Entity @IdClass(EmployeeSkillSet.Key.class)
public class EmployeeSkillSet implements Serializable {
private @Id @ManyToOne Employee employee;
private @Id @ManyToOne SkillSet skillSet;
private @Basic int numberOfYears;
public static class Key implements Serializable {
private Long employee; // plus getter+setter
private Long skillSet; // plus getter+setter
// plus hashCode, equals
}
}
尽管出于性能原因,您可以使用 @ManyToMany 批注更好,但定义两个多对一关系以便为多对多关系建模。
你需要4个神器,有
- 员工实体
- 技能组合实体
- EmployeeSkillSet Relation实体(这里可以指定numberOfYears列)
- EmployeeSkillSetPK(EmployeeSkillSet 关系实体的主键)
代码应该是这样的
员工
package <your_package>;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Entity
@Table(name="EMPLOYEE")
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="EMPLOYEEID")
private int id;
// Rest of columns and getter and setters for all
}
技能组合
package <your_package>;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
*
*/
@Entity
@Table(name="SKILLSET")
public class SkillSet implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
@Column(name="SKILLSETID")
private int id;
// Rest of columns and getter and setters for all
}
EmployeeSkillSetPK
/**
*
*/
package <your_package>;
import java.io.Serializable;
import javax.persistence.Embeddable;
/**
*
*/
@Embeddable
public class EmployeeSkillSetPK implements Serializable {
@ManyToOne
private Employee emp;
@ManyToOne
private SkillSet sk;
/**
* @return the employee
*/
public Employee getEmployee() {
return emp;
}
/**
* @param employee the employee to set
*/
public void setEmployee(Employee employee) {
this.employee = employee;
}
/**
* @return the sk
*/
public SkillSet getSkillSet() {
return sk;
}
/**
* @param sk the sk to set
*/
public void setSkillSet(SkillSet sk) {
this.sk = sk;
}
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
EmployeeSkillSetPK that = (EmployeeSkillSetPK) o;
if (employee != null ? !employee.equals(that.employee) : that.employee != null) {
return false;
}
if (sk != null ? !sk.equals(that.sk) : that.sk != null) {
return false;
}
return true;
}
public int hashCode() {
int result;
result = (employee != null ? employee.hashCode() : 0);
result = 31 * result + (sk != null ? sk.hashCode() : 0);
return result;
}
}
EmployeeSkillSet
/**
*
*/
package <your_package>;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.IdClass;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
/**
*
*/
@Entity
@Table(name="EMPLOYEESKILLSET")
@AssociationOverrides({ @AssociationOverride(name = "pk.employee", joinColumns = @JoinColumn(name = "EMPLOYEEID")),
@AssociationOverride(name = "pk.sk", joinColumns = @JoinColumn(name = "SKILLSETID")) })
public class EmployeeSkillSet implements Serializable {
@EmbeddedId
private EmployeeSkillSetPK pk = new EmployeeSkillSetPK();
@Column
private Integer numberOfYears;
@Transient
public Employee getEmployee() {
return pk.getEmployee();
}
public void setEmployee(Employee employee) {
pk.setEmployee(employee);
}
@Transient
public SkillSet getSkillSet() {
return pk.getSkillSet();
}
public void setSkillSet(SkillSet sk) {
pk.setSkillSet(sk);
}
public Integer getNumbersOfYears() {
return numberOfYears;
}
public void setNumbersOfYears(Integer numberOfYears) {
this.numberOfYears = numberOfYears;
}
}
这是针对 JPA 1.0 的,我现在无法测试代码,但它应该可以工作。
请注意,table 和列名是我自己写的。随意改编。