在这段代码中,如何为组合键生成一个Java类(如何在hibernate中组合键):
create table Time (
levelStation int(15) not null,
src varchar(100) not null,
dst varchar(100) not null,
distance int(15) not null,
price int(15) not null,
confPathID int(15) not null,
constraint ConfPath_fk foreign key(confPathID) references ConfPath(confPathID),
primary key (levelStation, confPathID)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
假设你有以下数据库表:
首先,你需要创建包含复合标识符的@Embeddable:
@Embeddable
public class EmployeeId implements Serializable {
@Column(name = "company_id")
private Long companyId;
@Column(name = "employee_number")
private Long employeeNumber;
public EmployeeId() {
}
public EmployeeId(Long companyId, Long employeeId) {
this.companyId = companyId;
this.employeeNumber = employeeId;
}
public Long getCompanyId() {
return companyId;
}
public Long getEmployeeNumber() {
return employeeNumber;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof EmployeeId)) return false;
EmployeeId that = (EmployeeId) o;
return Objects.equals(getCompanyId(), that.getCompanyId()) &&
Objects.equals(getEmployeeNumber(), that.getEmployeeNumber());
}
@Override
public int hashCode() {
return Objects.hash(getCompanyId(), getEmployeeNumber());
}
}
有了这些,我们可以映射使用复合标识符的Employee实体,方法是用@EmbeddedId注释它:
@Entity(name = "Employee")
@Table(name = "employee")
public class Employee {
@EmbeddedId
private EmployeeId id;
private String name;
public EmployeeId getId() {
return id;
}
public void setId(EmployeeId id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Phone实体与Employee有@ManyToOne关联,需要通过两个@JoinColumnmappings从父类引用复合标识符:
@Entity(name = "Phone")
@Table(name = "phone")
public class Phone {
@Id
@Column(name = "`number`")
private String number;
@ManyToOne
@JoinColumns({
@JoinColumn(
name = "company_id",
referencedColumnName = "company_id"),
@JoinColumn(
name = "employee_number",
referencedColumnName = "employee_number")
})
private Employee employee;
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = number;
}
}
另一种选择是将is映射为ConfPath表中复合元素的map。
不过,这种映射将受益于(ConfPathID,levelStation)上的索引。
public class ConfPath {
private Map<Long,Time> timeForLevelStation = new HashMap<Long,Time>();
public Time getTime(long levelStation) {
return timeForLevelStation.get(levelStation);
}
public void putTime(long levelStation, Time newValue) {
timeForLevelStation.put(levelStation, newValue);
}
}
public class Time {
String src;
String dst;
long distance;
long price;
public long getDistance() {
return distance;
}
public void setDistance(long distance) {
this.distance = distance;
}
public String getDst() {
return dst;
}
public void setDst(String dst) {
this.dst = dst;
}
public long getPrice() {
return price;
}
public void setPrice(long price) {
this.price = price;
}
public String getSrc() {
return src;
}
public void setSrc(String src) {
this.src = src;
}
}
映射:
<class name="ConfPath" table="ConfPath">
<id column="ID" name="id">
<generator class="native"/>
</id>
<map cascade="all-delete-orphan" name="values" table="example"
lazy="extra">
<key column="ConfPathID"/>
<map-key type="long" column="levelStation"/>
<composite-element class="Time">
<property name="src" column="src" type="string" length="100"/>
<property name="dst" column="dst" type="string" length="100"/>
<property name="distance" column="distance"/>
<property name="price" column="price"/>
</composite-element>
</map>
</class>