在这段代码中,如何为组合键生成一个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;
}
}
让我们举一个简单的例子。假设有两个表,分别叫test和customer,描述如下:
create table test(
test_id int(11) not null auto_increment,
primary key(test_id));
create table customer(
customer_id int(11) not null auto_increment,
name varchar(50) not null,
primary key(customer_id));
还有一个表用于跟踪测试和客户:
create table tests_purchased(
customer_id int(11) not null,
test_id int(11) not null,
created_date datetime not null,
primary key(customer_id, test_id));
我们可以看到,在表tests_bought中,主键是一个复合键,因此我们将使用<composite-id…>…</composite-id hbm.xml映射文件中的>标签。因此PurchasedTest.hbm.xml看起来像这样:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="entities.PurchasedTest" table="tests_purchased">
<composite-id name="purchasedTestId">
<key-property name="testId" column="TEST_ID" />
<key-property name="customerId" column="CUSTOMER_ID" />
</composite-id>
<property name="purchaseDate" type="timestamp">
<column name="created_date" />
</property>
</class>
</hibernate-mapping>
但这并没有结束。在Hibernate中我们使用session。load (entityClass, id_type_object)使用主键查找并加载实体。在组合键的情况下,ID对象应该是一个单独的ID类(在上面的情况下是purchasedtestd类),它只声明主键属性如下:
import java.io.Serializable;
public class PurchasedTestId implements Serializable {
private Long testId;
private Long customerId;
// an easy initializing constructor
public PurchasedTestId(Long testId, Long customerId) {
this.testId = testId;
this.customerId = customerId;
}
public Long getTestId() {
return testId;
}
public void setTestId(Long testId) {
this.testId = testId;
}
public Long getCustomerId() {
return customerId;
}
public void setCustomerId(Long customerId) {
this.customerId = customerId;
}
@Override
public boolean equals(Object arg0) {
if(arg0 == null) return false;
if(!(arg0 instanceof PurchasedTestId)) return false;
PurchasedTestId arg1 = (PurchasedTestId) arg0;
return (this.testId.longValue() == arg1.getTestId().longValue()) &&
(this.customerId.longValue() == arg1.getCustomerId().longValue());
}
@Override
public int hashCode() {
int hsCode;
hsCode = testId.hashCode();
hsCode = 19 * hsCode+ customerId.hashCode();
return hsCode;
}
}
重要的一点是,我们还实现了hashCode()和equals()两个函数,因为Hibernate依赖于它们。
使用hbm.xml
<composite-id>
<!--<key-many-to-one name="productId" class="databaselayer.users.UserDB" column="user_name"/>-->
<key-property name="productId" column="PRODUCT_Product_ID" type="int"/>
<key-property name="categoryId" column="categories_id" type="int" />
</composite-id>
使用注释
复合键类
public class PK implements Serializable{
private int PRODUCT_Product_ID ;
private int categories_id ;
public PK(int productId, int categoryId) {
this.PRODUCT_Product_ID = productId;
this.categories_id = categoryId;
}
public int getPRODUCT_Product_ID() {
return PRODUCT_Product_ID;
}
public void setPRODUCT_Product_ID(int PRODUCT_Product_ID) {
this.PRODUCT_Product_ID = PRODUCT_Product_ID;
}
public int getCategories_id() {
return categories_id;
}
public void setCategories_id(int categories_id) {
this.categories_id = categories_id;
}
private PK() { }
@Override
public boolean equals(Object o) {
if ( this == o ) {
return true;
}
if ( o == null || getClass() != o.getClass() ) {
return false;
}
PK pk = (PK) o;
return Objects.equals(PRODUCT_Product_ID, pk.PRODUCT_Product_ID ) &&
Objects.equals(categories_id, pk.categories_id );
}
@Override
public int hashCode() {
return Objects.hash(PRODUCT_Product_ID, categories_id );
}
}
实体类
@Entity(name = "product_category")
@IdClass( PK.class )
public class ProductCategory implements Serializable {
@Id
private int PRODUCT_Product_ID ;
@Id
private int categories_id ;
public ProductCategory(int productId, int categoryId) {
this.PRODUCT_Product_ID = productId ;
this.categories_id = categoryId;
}
public ProductCategory() { }
public int getPRODUCT_Product_ID() {
return PRODUCT_Product_ID;
}
public void setPRODUCT_Product_ID(int PRODUCT_Product_ID) {
this.PRODUCT_Product_ID = PRODUCT_Product_ID;
}
public int getCategories_id() {
return categories_id;
}
public void setCategories_id(int categories_id) {
this.categories_id = categories_id;
}
public void setId(PK id) {
this.PRODUCT_Product_ID = id.getPRODUCT_Product_ID();
this.categories_id = id.getCategories_id();
}
public PK getId() {
return new PK(
PRODUCT_Product_ID,
categories_id
);
}
}
假设你有以下数据库表:
首先,你需要创建包含复合标识符的@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;
}
}