--------------Hibernate学习(四) 多对一映射 和 一对多映射
现实中有很多场景需要用到多对一或者一对多,比如上面这两个类图所展现出来的,一般情况下,一个部门会有多名员工,一名员工只在一个部门任职。
多对一关联映射
在上面的场景中,对于Employee来说,它跟Department的关系就是多对一。
先写实体类
Employee.java
package entity;
public class Employee {
public int id;
public String name;
public Department department;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Department getDepartment() {
return department;
}
public void setDepartment(Department department) {
this.department = department;
}
}Department.java
package entity;
public class Department {
public int id;
public String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}配置多对一关系时,设计实体类时,除了写出最基本的属性(比如Employee的id、name),在对应“多”的那个类(比如Employee.java)中添加对应“一”那个类的引用(比如上面的department)。
映射文件
Employee.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="entity.Employee" table="t_employee">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<many-to-one name="department" column="departmentid"/>
</class>
</hibernate-mapping>Department.hbm.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<<hibernate-mapping>
<class name="entity.Department" table="t_Department">
<id name="id">
<generator class="native"/>
</id>
<property name="name"></property>
</class>
</hibernate-mapping>映射文件中的内容基本上跟它关联的类中的字段都是对应的。主键配置在<id></id>中,基本字段配置在<property/>中,对其他类的引用配置在<many-to-one/>中。
建表
drop table t_department<br />drop table if exists t_employee<br />--建表<br />create table t_department (id integer primary key , name varchar(255));<br />--建序列<br />CREATE SEQUENCE department_sequence<br />INCREMENT BY 1 -- 每次加几个<br />START WITH 1 -- 从1开始计数<br />NOMAXVALUE -- 不设置最大值<br />NOCYCLE -- 一直累加,不循环<br />NOCACHE -- 不建缓冲区<br />--建立触发器<br />create trigger t_department_trig before<br />insert on t_department for each row when (new.id is null)<br />begin<br /> select department_sequence.nextval into:new.id from dual;<br />end;<br />创建表<br />create table t_employee (id integer primary key , name varchar(255), departmentid integer);<br />--建序列<br />CREATE SEQUENCE employee_sequence<br />INCREMENT BY 1 -- 每次加几个<br />START WITH 1 -- 从1开始计数<br />NOMAXVALUE -- 不设置最大值<br />NOCYCLE -- 一直累加,不循环<br />NOCACHE -- 不建缓冲区<br />NOCACHE -- 不建缓冲区<br />--建立触发器<br />create trigger t_employee_trig before<br />insert on t_employee for each row when (new.id is null)<br />begin<br /> select employee_sequence.nextval into:new.id from dual;<br />end;<br />--创建外键关联<br />alter table t_employee add constraint fk_departmentid foreign key (departmentid) references t_department(id);
一执行,发现报错了:
org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: entity.Department
一看错误就知道,这是因为department还在Transient状态时,session是不能对其操作的。所以可以在事务提交之前先save一下department:
session.beginTransaction();
Department department=new Department();
department.setName("信息部");
Employee employee1=new Employee();
employee1.setName("小胡");
employee1.setDepartment(department);
Employee employee2=new Employee();
employee2.setName("小玉");
employee2.setDepartment(department);
session.save(department);
session.save(employee1);
session.save(employee2);
session.getTransaction().commit();