Hibernate复合主键中其中有主键是引用外键情况下的配置方法

来源:互联网 发布:js 格式化字符串 编辑:程序博客网 时间:2024/05/04 19:57

这个有两种配置方式。一种是映射一个也是复合主键一部分的外键列,通过一般的<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版本中得以实现)。

0 0