Hibernate複合主鍵中其中有主鍵是引用外來鍵情況下的配置方法
阿新 • • 發佈:2019-02-03
這個有兩種配置方式。一種是對映一個也是複合主鍵一部分的外來鍵列,通過一般的<many-to-one>元素,並用insert="false" update="false"禁用該列的任何Hibernate插入或者更新。另一種方式是<key-many-to-one>。下面分別說明兩種方式的配置方法。
1、many-to-one方式
假設有兩個表USER和DEPARTMENT表。兩個表的結構建立SQL語句如下:
create table DEPARTMENT ( DEPARTMENT_ID varchar(255) not null, DEPARTMENT_NAME varchar(255), DEPARTMENT_ADDRESS varchar(255), primary key (DEPARTMENT_ID) ); create table USER ( USERNAME varchar(255) not null, DEPARTMENT_ID varchar(255) not null, FIRSTNAME varchar(255), LASTNAME varchar(255), primary key (USERNAME, DEPARTMENT_ID) ); alter table USER add constraint FK27E3CBF9776336 foreign key (DEPARTMENT_ID) references DEPARTMENT;
可以看到USER表的主鍵是由(USERNAME, DEPARTMENT_ID)聯合主鍵構成的。其中列DEPARTMENT_ID是引用表DEPARTMENT中DEPARTMENT_ID列的外來鍵。
根據表結構生成的Java類如下:
首先需要構建一個聯合主鍵類UserId.java
package hello; import java.io.Serializable; /** * Created by orz on 16-2-28. */ public class UserId implements Serializable { private String username; private String departmentId; public UserId() { } public UserId(String username, String departmentId) { this.username = username; this.departmentId = departmentId; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getDepartmentId() { return departmentId; } public void setDepartmentId(String departmentId) { this.departmentId = departmentId; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; UserId userId = (UserId) o; if (username != null ? !username.equals(userId.username) : userId.username != null) return false; return departmentId != null ? departmentId.equals(userId.departmentId) : userId.departmentId == null; } @Override public int hashCode() { int result = username != null ? username.hashCode() : 0; result = 31 * result + (departmentId != null ? departmentId.hashCode() : 0); return result; } }
User.java 如下:
package hello; /** * Created by orz on 16-2-28. */ public class User { private UserId userId; private String firstName; private String lastName; private Department department; public UserId getUserId() { return userId; } public void setUserId(UserId userId) { this.userId = userId; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } }
Department.java 如下:
package hello;
/**
* Created by orz on 16-2-28.
*/
public class Department {
private String departmentId;
private String departmentName;
private String address;
public String getDepartmentId() {
return departmentId;
}
public void setDepartmentId(String departmentId) {
this.departmentId = departmentId;
}
public String getDepartmentName() {
return departmentName;
}
public void setDepartmentName(String departmentName) {
this.departmentName = departmentName;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
建立的配置檔案如下:
Department.hbm.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="hello.Department" table="DEPARTMENT">
<id name="departmentId" column="DEPARTMENT_ID">
<generator class="assigned" />
</id>
<property name="departmentName" column = "DEPARTMENT_NAME" />
<property name="address" column = "DEPARTMENT_ADDRESS" />
</class>
</hibernate-mapping>
User.hbm.xml:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="hello.User" table="USER">
<composite-id name="userId" class="hello.UserId">
<key-property name="username" column="USERNAME" />
<key-property name="departmentId" column="DEPARTMENT_ID" />
</composite-id>
<property name="firstName" column = "FIRSTNAME" />
<property name="lastName" column = "LASTNAME" />
<many-to-one name="department" class="hello.Department" column="DEPARTMENT_ID" insert="false" update="false" />
</class>
</hibernate-mapping>
測試類如下:
package hello;
import org.hibernate.Session;
import org.hibernate.Transaction;
import persistence.HibernateUtil;
import java.util.Iterator;
import java.util.List;
/**
* Created by orz on 16-2-21.
*/
public class HelloWorld {
public static void main(String[] args) {
Session departmentSession = HibernateUtil.getSessionFactory().openSession();
Transaction departmentTa = departmentSession.beginTransaction();
Department department = new Department();
department.setDepartmentId("1");
department.setDepartmentName("university");
department.setAddress("xi'an");
departmentSession.save(department);
departmentTa.commit();
departmentSession.close();
Session userSession1 = HibernateUtil.getSessionFactory().openSession();
Transaction userTa1 = userSession1.beginTransaction();
UserId userId = new UserId("zxwei",department.getDepartmentId());
User user = new User();
user.setUserId(userId);
user.setFirstName("zx");
user.setLastName("wei");
user.setDepartment(department);
userSession1.saveOrUpdate(user);
userTa1.commit();
userSession1.close();
Session userSession2 = HibernateUtil.getSessionFactory().openSession();
Transaction userTa2 = userSession2.beginTransaction();
List users = userSession2.createQuery("from User u").list();
System.out.println(users.size() + " user(s) found");
for (Iterator iter = users.iterator(); iter.hasNext();) {
User iuser = (User) iter.next();
System.out.println("User: " + iuser.getUserId().getUsername() + ", "
+ iuser.getUserId().getDepartmentId() + ", " + iuser.getFirstName() + ", " + iuser.getLastName()
+", department: " + iuser.getDepartment().getDepartmentName() + ", " + iuser.getDepartment().getAddress());
}
userTa2.commit();
userSession2.close();
//Shutting down the application
HibernateUtil.shutdown();
}
}
經測試成功執行。其中的HibernateUtil類可以參考我的另一篇部落格:“ Hibernate one-to-one 複合主鍵相同的mapping檔案配置方法 ”。
2、key-many-to-one方式
大致的配置如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="hello.User" table="USER">
<composite-id name="userId" class="hello.UserId">
<key-property name="username" column="USERNAME" />
<key-many-to-one name="department" class="hello.Department" column="DEPARTMENT_ID" />
</composite-id>
<property name="firstName" column = "FIRSTNAME" />
<property name="lastName" column = "LASTNAME" />
</class>
</hibernate-mapping>
這個我沒有經過測試。不建議使用這種方式。因為在複合標識類中有關聯通常並不方便,因此除非特殊情況下,否則不推薦這種方法。<key-many-to-one>構造在查詢方面也有限制:你無法限制一個跨<key-many-to-one>聯接的HQL或者Criteria的查詢結果(雖然這些特性可能將在以後的HIbernate版本中得以實現)。