Hibernate JPA OneToMany複合鍵(Compound Key)設定如下。
本篇範例複合鍵是在子表(Many端)。
例如有三個資料表分別為Department
,Region
及Employee
關係如下。
+----------------+
| Employee | +----------------+
+--------------+ +----------------+ | Department |
| Region | |PK|EmployeeId |* 1+----------------+
+--------------+1 *|FK|DepartmentId +----------+PK|DepartmentId |
|PK|RegionId +----------+FK|RegionId | | | |
| | | +----------------+ +--+-------------+
+--+-----------+
Employee
的主鍵為複合主鍵,由本身的EmployeeId
及外鍵RegionId
,DepartmentId
組成,則JPA的Entiy設定如下。
Employee.java
@Entity
@Table(name="Employee")
public class Employee {
@EmbeddedId
private EmployeePk employeePk;
// getter and setter ommitted
}
Employee
因為是複合主鍵,所以要使用@EmbeddedId
及一個@Embeddable
類別EmployeePk
來設定。
EmployeePk.java
@Embeddable
public class EmployeePk implements Serializable{
@Column(name="EmployeeId")
private int employeeId;
@ManyToOne
@JoinColumn(name="departmentId") // Department的@Id變數名稱
private Department department;
@ManyToOne
@JoinColumn(name="regionId") // Region的@Id變數名稱
private Region region;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EmployeePk)) return false;
EmployeePk that = (EmployeePk) o;
return (region.getRegionId() == that.region.getRegionId() &&
department.getDepartmentId() == that.department.getDepartmentId() &&
getEmployeeId() == that.getEmployeeId());
}
@Override
public int hashCode() {
return Objects.hash(region.getRegionId(), department.getDepartmentId(), getEmployeeId());
}
// getter and setter ommitted
}
Department.java
@Entity
@Table(name="Department")
public class Department {
@Id
@Column(name="DepartmentId")
private int departmentId;
@OneToMany(mappedBy="employeePk.department") // Employee的@EmbeddedId變數名稱.@ManyToOne的變數名稱
private List<Employee> employeeList;
}
注意@OneToMany
的mappedBy
屬性設定。而fetch
維持預設的LAZY
,不要設為EAGER
,否則employeeList
會出現重複的資料。
Region.java
@Entity
@Table(name="Region")
public class Region {
@Id
@Column(name="RegionId")
private int regionId;
@OneToMany(mappedBy="employeePk.region")
private List<Employee> employeeList;
// getter and setter ommitted
}
下面是另一種設定方式,改用@MapId
來指明EmployeePk
中對應的屬性,效果相同
Employee.java
@Entity
@Table(name="Employee")
public class Employee {
@EmbeddedId
private EmployeePk employeePk;
@MapsId("departmentId")
@ManyToOne
@JoinColumn(name="departmentId")
private Department department;
@MapsId("regionId")
@ManyToOne
@JoinColumn(name="regionId")
private Region region;
// getter and setter ommitted
}
EmployeePk.java
@Embeddable
public class EmployeePk implements Serializable {
@Column(name="EmployeeId")
private int employeeId;
public int departmentId;
public int regionId;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EmployeePk)) return false;
EmployeePk that = (EmployeePk) o;
return (getRegionId() == that.getRegionId() &&
getDepartmentId() == that.getDepartmentId() &&
getEmployeeId() == that.getEmployeeId());
}
@Override
public int hashCode() {
return Objects.hash(getRegionId(), getDepartmentId(), getEmployeeId());
}
// getter and setter ommitted
}
Department
與Region
設定同上。
然後@Embeddable
類別要實作Serializable
,否則會出現錯誤。
沒有留言:
張貼留言