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

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

你可能感兴趣的:(Hibernate,复合主键,外键引用)