Hibernate一对多、多对一映射
在自然界中事事物物纷纷扰扰,关系错综复杂,迷迷离离,我们不是在逃避关系而是我们忽略了这种错错综综的关系。那么作为一个程序员,在我们的世界中一切皆有联系,皆可以用程序去构建这个世界。这样或那样的联系有时候就产生了各种对应关系。
在我们的生活中存在着这样或者那样对应关系其中今天要讨论的是一对多、多对一关系,比如一颗大树有很多的叶子,每片叶子只能属于一棵大树。又比如公司中的一个部门有很对多员工,但是每个员工只能属于一个部门。这样的例子很多很多,所以今天我就根据Hibernate中的一对多、多对一映射。
我们就拿公司中部门和员工的关系举例子。首先反应在Department.java代码中是如下面这样的:
public class Department {
private Integer id;
private String name;
private Set<Employee> employees;
public Department() {
}
//各种属性的get和set方法
}
然后是Employee.java
public class Employee {
private Integer id;
private String name;
private String position;
private int salary;
private Department department;
public Employee() {
// TODO Auto-generated constructor stub
}
//属性的get和set方法
}
然后在Department.hbm.xml中的配置如下:
<class name="com.school.domain.Department" table="department">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="employees">
<key column="departmentId"></key>
<one-to-many class="com.school.domain.Employee" />
</set>
</class>
然后在Employee.hbm.xml中的配置如下:
<class name="com.school.domain.Employee" table="employee">
<id name="id">
<generator class="native"></generator>
</id>
<property name="name"></property>
<property name="position"></property>
<property name="salary"></property>
<many-to-one name="department" lazy="false" column="departmentId"
class="com.school.domain.Department"></many-to-one>
</class>
然后特别需要注意的是DepartmentDao中保存的代码,这里特别需要注意的是有时候在具体的业务场景中并不是这样保存employee的,更多的是用EmployeeDao里面的save方法进行保存,但是一定要给Department对象的employees属性给设值才能指定一对多的关系:
public void saveDepartment(Department department) {
Session session = DBUtil.getSessionFactory().openSession();
Transaction transaction = null;
try {
transaction = session.beginTransaction();
for (Employee employee : department.getEmployees()) {
session.save(employee);
}
session.save(department);
transaction.commit();
} catch (Exception e) {
e.printStackTrace();
transaction.rollback();
} finally {
session.close();
}
}
生成的表结构如下:
如上配置就做好了部门与雇员的一对多、多对一的编码。现在我们进行测试方法:
保存方法测试
@Test
public void testSave() {
Department department = new Department();
department.setName("002");
Set<Employee> employees=new HashSet<Employee>();
Employee emeploy1 = new Employee("001", "清洁工", 1000, department);
Employee emeploy2 = new Employee("002", "员工", 2000, department);
Employee emeploy3 = new Employee("003", "经理", 6000, department);
employees.add(emeploy1);
employees.add(emeploy2);
employees.add(emeploy3);
department.setEmployees(employees);
depmentDao.saveDepartment(department);
}
解除关系测试
@Test
public void removeRationship(){
//解除id为13的employee对应的Department的关系
Employee employee = emeployDao.getEmployee(13);
employee.setDepartment(null);
emeployDao.updateEmployee(employee);
//解除Department与之对应的Employees的关系
Department department = depmentDao.getDepartment(5);
department.getEmployees().clear();
depmentDao.updateDepartment(department);
}
删除:
@Test
public void remove(){
//删除Employee
Employee employee = emeployDao.getEmployee(17);
emeployDao.removeEmployee(employee);
/**
* 该方法会删除department表中Id为6的元组,
* 对应的employee并不会被删除只是解除了和department的关系
*/
Department department = depmentDao.getDepartment(6);
depmentDao.removeDepartment(department);
}
当然一对多、多对一也可以用其他的集合来进行比如List、Map、Array等但是在没有特殊的业务需要建议使用set来进行映射,因为像List和Array因为是有顺序的所以再删除的时候会要进行一些额外的操作。比如List结构的中有5个Employee,我们删除了<list-index>索引的前两个,那么我们在获取Department的employees的size的时候依然是5,因为其list-index的最大值依然是五。单丝Set因为是无序的所以不存在这个问题