Hibernate读书笔记-----Hibernate的关联映射之N-1关联映射
来源:互联网 发布:新浪ip反查域名 编辑:程序博客网 时间:2024/05/18 02:08
我们所生活的世界很少有事物是孤立存在的,每个事物必然会存在着与它相关联的事物。在面向对象设计当中,关联关系是非常重要的。关联关系一般可以分为以下两种:
单向关系:只需单向访问关联端
双向关系:关联的两端都可以互相访问
单向关系可分为:1—N、1—1、N—1、N—N
双向关系可分为:1—1 、1—N、N—N
下面就上面的每种关联映射分别讲解:
一、N—1关联映射
1、单向N—1关联
1.1、无连接表的N-1关联(基于外键的N-1关联)
对于单向的N—1关联而言只需要从N的一端可以访问1的一端。为了让这个两个持久化类支持这种关联映射,程序应该在N的一端的持久化类中增加一个熟悉,该属性引用1一端的关联实体。
两个关联属性如下(以员工和部门之间的关系为例):
Employee:
- public class Employee {
- private Integer id;
- private String name;
- private Department department; //关联属性
- public Integer getId() {
- return id;
- }
- public void setId(Integer 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:
- public class Department {
- private Integer id;
- private String name;
- private Set<Employee> employees;
- public Integer getId() {
- return id;
- }
- public void setId(Integer id) {
- this.id = id;
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public Set<Employee> getEmployees() {
- return employees;
- }
- public void setEmployees(Set<Employee> employees) {
- this.employees = employees;
- }
- }
Employee端增加了Department属性,该属性并不是一个普通的组件属性,而是引用另一个持久化类的类。Hibernate使用<many-to-one.../>元素映射N—1的关联实体,直接采用<many-to-one.../>元素来映射关联实体将会在N的一端的数据表中增加一个外键,用于参照主表记录。
下面为两个实体的映射文件:
Employee.hbm.xml
在这个映射文件中需要用<many-to-one../>来完成关联映射
- <hibernate-mapping package="com.hibernate.domain">
- <class name="Employee" table="employee">
- <id name="id" column="employeeID">
- <generator class="native" />
- </id>
- <property name="name" column="employeeName" />
- <!-- 用于映射N-1关联实体,指定关联实体类为 :Department,指定外键为:departmentID-->
- <many-to-one class="Department" name="department" column="departmentID" not-null="true" cascade="all"/>
- </class>
- </hibernate-mapping>
Department.hbm.xml
- <hibernate-mapping package="com.hibernate.domain" >
- <class name="Department" table="department">
- <id name="id" column="departmentID">
- <generator class="native" />
- </id>
- <property name="name" column="departmentName" />
- </class>
- </hibernate-mapping>
通过上面的映射后,就可以使用如下代码来保存Employee和Department实体了。
- //增加
- static void add() {
- Session s = null;
- Transaction tx = null;
- try {
- s = HibernateUtil.getSession();
- tx = s.beginTransaction();
- Department depart = new Department(); //....1
- depart.setName("组织部");
- Employee emp = new Employee();
- //对象模型:建立两个对象的关联关系
- emp.setDepartment(depart); //...2
- emp.setName("汤妹彤");
- s.save(depart); //...3
- s.save(emp); //...4
- tx.commit();
- } finally {
- if (s != null)
- s.close();
- }
- }
代码分析:
当代码运行到...1的时候会创建一个瞬态的Department对象。当程序运行到...3和...4的时候,系统就会分别保存Department对象和Employee对象。会产生如下两条SQL语句:
- Hibernate: insert into department (departmentName) values (?)
- e: insert into employee (employeeName, departmentID) values (?, ?)
...2这条语句非常重要,因为它是建立Department和Employee两个对象的关联关系。没有这条语句是无法建立两个对象的关系。
在这里我们将...3语句和...4两条语句交换位置。这时运行就会产生三条SQL语句。当...3的时候,departmentID插入的时候为空,只有当持久化Department对象后,系统就会将departmentID修改为相对应的值。如下:
- Hibernate: insert into employee (employeeName, departmentID) values (?, ?)
- Hibernate: insert into department (departmentName) values (?)
- Hibernate: update employee set employeeName=?, departmentID=? where employeeID=?
如果我们在Employee.hbm.xml映射文件中,给外键添加一个非空约束,即:
- <many-to-one class="Department" name="department" column="departmentID" not-null="true"/>
上面的代码就会报空异常:org.hibernate.PropertyValueException: not-null property references a null or transient value。
如果我们不想改变上面代码,又要能够执行。即先持久化从表。对于这种情况我们可以设置级联:cascade="all".即
- <many-to-one class="Department" name="department" column="departmentID" not-null="true" cascade="all"/>。
通过指定了cascade="all"。这就意味着系统将先自动级联插入主表记录。
所以在所有基于外键约束的关联关系中,我们必须牢记:要么总是先持久化主表对应的实体,要么设置级联操作。否则当Hibernate试图插入从表记录时,如果发现该从表参照的主表记录不存在,一定会抛出异常。
2、有连接表的N-1关联
对于绝大部分的单向N-1关联而言,使用基于外键的关联映射就可以了。但是如果需要使用连接表来映射单向N-1关联,则需要使用<join.../>元素,该元素用于强制将一个类的属性映射到多张表中。
使用<join.../>元素映射到连接表时,需要外键关联,应在配置文件中增加<key.../>子元素来映射外键,并为<join.../>元素增加<many-to-one.../>子元素来映射N-1的关联实体。如下:
- <hibernate-mapping package="com.hibernate.domain">
- <class name="Employee" table="employee">
- <id name="id" column="employeeID">
- <generator class="native" />
- </id>
- <property name="name" column="employeeName" />
- <!-- 使用join元素强制使用连接表 -->
- <join table="employee_department">
- <!-- 映射连接表中参照本表主键的外键列 -->
- <key column="employeeID" />
- <!-- 映射连接表参照关联实体的外键列 -->
- <many-to-one name="department" class="Department" column="departmentID" />
- </join>
- </class>
- </hibernate-mapping>
- Hibernate读书笔记-----Hibernate的关联映射之N-1关联映射
- Hibernate读书笔记-----Hibernate的关联映射之1-N关联映射
- Hibernate读书笔记-----Hibernate的关联映射之N-1关联映射
- Hibernate读书笔记-----Hibernate的关联映射之1-N关联映射
- Hibernate的关联映射之1-N关联映射
- Hibernate读书笔记-----Hibernate的关联映射之N-N关联映射 .
- Hibernate读书笔记-----Hibernate的关联映射之N-N关联映射 .
- Hibernate的关联映射之N-N关联映射 .
- Hibernate读书笔记-----Hibernate的关联映射之1-1关联映射
- Hibernate读书笔记-----Hibernate的关联映射之1-1关联映射
- Hibernate之1-N关联映射
- Hibernate的关联映射之1-1关联映射
- SSH之hibernate—1和n的关联映射
- Hibernate的关联映射(1)-单向N-1关联
- Hibernate的关联映射(3)-单向1-N关联
- Hibernate的关联映射(5)-双向1-N关联
- hibernate之关联映射
- Hibernate的关联映射
- 写作词语_环境资源交通
- Mac Usage Tips
- VS 2008, MFC: add OnInitDialog - how?
- SQLite指南(1) -- SQLite的特性
- SQLite指南(2) -- 帮助及编译SQLite
- Hibernate读书笔记-----Hibernate的关联映射之N-1关联映射
- SQLite指南(3) - 5分钟了解熟悉SQLite
- Android动画学习笔记
- itunes相关
- jQuery中创建实例与原型继承揭秘
- SQLite指南(4) - FAQ列表(important)
- 错误:无法访问android.app.Activity 找不到android.app.Activity 的解决方式
- SQLite指南(5) - PRAGMA命令用法(完整)
- Kanban的五个属性