Hibernate读书笔记-----Hibernate的关联映射之N-1关联映射

我们所生活的世界很少有事物是孤立存在的,每个事物必然会存在着与它相关联的事物。在面向对象设计当中,关联关系是非常重要的。关联关系一般可以分为以下两种:

单向关系:只需单向访问关联端

双向关系:关联的两端都可以互相访问

单向关系可分为:1N11N1NN

双向关系可分为:111NNN

下面就上面的每种关联映射分别讲解:

一、N1关联映射

1、单向N1关联

1.1、无连接表的N-1关联(基于外键的N-1关联)

对于单向的N1关联而言只需要从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 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 getEmployees() { return employees; } public void setEmployees(Set employees) { this.employees = employees; } }

Employee端增加了Department属性,该属性并不是一个普通的组件属性,而是引用另一个持久化类的类。Hibernate使用元素映射N1的关联实体,直接采用元素来映射关联实体将会在N的一端的数据表中增加一个外键,用于参照主表记录。

下面为两个实体的映射文件:

Employee.hbm.xml

在这个映射文件中需要用来完成关联映射

Department.hbm.xml

通过上面的映射后,就可以使用如下代码来保存EmployeeDepartment实体了。

//增加 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 (?) Hibernate: insert into employee (employeeName, departmentID) values (?, ?)

...2这条语句非常重要,因为它是建立DepartmentEmployee两个对象的关联关系。没有这条语句是无法建立两个对象的关系。

在这里我们将...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映射文件中,给外键添加一个非空约束,即:

上面的代码就会报空异常:org.hibernate.PropertyValueException:not-nullpropertyreferencesanullortransientvalue

如果我们不想改变上面代码,又要能够执行。即先持久化从表。对于这种情况我们可以设置级联:cascade="all".

通过指定了cascade="all"这就意味着系统将先自动级联插入主表记录。

所以在所有基于外键约束的关联关系中,我们必须牢记:要么总是先持久化主表对应的实体,要么设置级联操作。否则当Hibernate试图插入从表记录时,如果发现该从表参照的主表记录不存在,一定会抛出异常。

2、有连接表的N-1关联

对于绝大部分的单向N-1关联而言,使用基于外键的关联映射就可以了。但是如果需要使用连接表来映射单向N-1关联,则需要使用元素,该元素用于强制将一个类的属性映射到多张表中。

使用元素映射到连接表时,需要外键关联,应在配置文件中增加子元素来映射外键,并为元素增加子元素来映射N-1的关联实体。如下:


读李刚《轻量级JavaEE 企业应用实战》

你可能感兴趣的:(Hibernate读书笔记-----Hibernate的关联映射之N-1关联映射)