单向·1-n关联只需从1的一端可以访问n的一端.
在实际开发里面,关于一对多和多对一,有一个设计原则:尽量避免去使用一对多这种关系,而应该多使用多对一这种关系.但有时候不可避免的,例如:订单和订单项就是一对多的这种关系,一个订单里面有多个订单项,在显示订单的时候一定要显示多方的数据的,即订单项,这时候我们就必须设计这种关系了.如果你没有设计这种关系,这时候从数据库里面找出订单的基本信息,人家一看订单,只能看到订单的基本信息,不能看到订单项,这是不行的。如果这时候不可避免的要设计这种关系(一对多这种关系),并且订单项有上千万条的数据,那么千万不能直接将其找出来,一定要采用分页的方式去找。
首先两个实体类,一个部门类,一个职工类:
Department.java
package hibernate.model.o2m;
import java.util.HashSet;
import java.util.Set;
//部门(one)
public class Department {
private Integer id;
private String name;
private Set<Employee> employeeSet = new HashSet<Employee>();
//此处省略get,set方法
}
Employee.java
package hibernate.model.o2m;
//员工(many)
public class Employee {
private Integer id;
private String name;
//此处省略get,set方法
}
Employee类的映射文件:Employee.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibernate.model.o2m">
<class name="Employee" table="e_emp">
<id name="id" column="e_id">
<!-- 设置成increment之后,会从数据库中查找主键id最大的值,然后+1进行存储 -->
<generator class="increment"></generator>
</id>
<property name="name" column="e_name"></property>
</class>
</hibernate-mapping>
Department.hbm.xml映射文件
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hibernate.model.o2m">
<class name="Department" table="d_dept">
<id name="id" column="d_id">
<!-- 设置为native之后,主键会按照本来的顺序进行增长(比如之前11但是删除了,现在就从12开始) -->
<generator class="native"></generator>
</id>
<property name="name" column="d_name"></property>
<!--
inverse:默认为false, 指关联关系的控制权由自己来维护
inverse设置为true的时候,就说明关联在多的那一方被维护 (一般设置在多的一方去维护,效率会跟高一点)
-->
<set name="employeeSet" cascade="all" lazy="false">
<key column="d_id"></key>
<one-to-many class="Employee" />
</set>
</class>
</hibernate-mapping>
One-To-Many测试类
package hibernate.model.o2m;
import java.util.Set;
import org.hibernate.Session;
import org.junit.Test;
import xh.util.HibernateUtil;
import hibernate.model.o2m.Department;
//单向一对多
public class O2mTest {
private Session session;
public O2mTest() {
session = HibernateUtil.getInstance().getSession();
}
// 保存
@Test
public void o2mTest() {
session.beginTransaction();
Employee emp1 = new Employee();
emp1.setName("员工1");
Employee emp2 = new Employee();
emp2.setName("员工2");
Department dept = new Department();
dept.setName("财务部");
dept.getEmployeeSet().add(emp1);
dept.getEmployeeSet().add(emp2);
try {
//用了级联
session.save(dept);
/*session.save(emp1);
session.save(emp2);*/
session.beginTransaction().commit();
session.close();
} catch (Exception e) {
session.beginTransaction().rollback();
}
}
@Test
public void testQuery() {
Department department = (Department) session.get(Department.class, 1);
Set<Employee> set = department.getEmployeeSet();
System.out.print("部门Id为1的员工:");
for (Employee employee2 : set) {
System.out.print(employee2.getName()+",");
}
}
}
单向一对多:实体之间的关系由"一"的一端加载"多"的一端,关系由"一"的一端持有"多"的一端的集合.在我们加载"一"的时候把多也加载进来了,也就是部门中维护职工的集合。我们可以根据部门找到属于这些部门的所有职工.但不能根据职工找到属于它所属的部门
为什么会有5条sql语句,进行insert之后为什么还要update呢?
因为单向一对多关系是在”一”的一方维护数据,多的一方Employee并不知道有Department的存在。所以在保存Employee的时候,关系字段did是为null的。如果把did字段设置为非空,则无法保存数据。
因为Employee不维护关系,而是由Department来维护关系,则在对Department进行操作的时候,就会发出多余的update语句,去维持Department与Employee的关系,这样加载Department的时候才会把该Department对应的职工加载进来。所以会多两条udate语句。这样的效率是非常低的。
为了提高效率,我们一般会采用双向一对多关联的方式。