hibernate (五) 一对多 oneToMany

直接上例子:
部门和员工的关系:
一个部门可以有多个员。一个员工只属于一个部门。

目录结构:
这里写图片描述

Employee.java

public class Employee {
    private Integer id;
    private String name;
    private Department department; // 关联的部门对象

Department.java

public class Department {
    private Integer id;
    private String name;
    private Set<Employee> employees = new HashSet<Employee>(); // 关联多个员工

部门和员工的映射文件。
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="com.zll.test">
    <class name="Department" table="department">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name"/>

        <!-- employees属性,Set集合,表达的是本类与Employee的一对多 
            class属性:关联的实体类型
            key子元素:对方表中的外键列(多方的那个表)

            inverse属性:(对查询获取数据没有影响)
                默认为false,表示本方维护关联关系。
                如果为true,表示本方不维护关联关系。
                只是影响数据的插入和删除时,否能可以以联动修改外键列的值(设成有效值或是null值)。

            cascade属性:
                默认为none,代表不级联。
                级联是指操作主对象时,对关联的对象也做相同的操作。
                可设为:delete, save-update, all, none ...
        -->
        <set name="employees" cascade="all" inverse="true">
            <key column="departmentId"></key>
            <one-to-many class="Employee"/>
        </set>
    </class>
</hibernate-mapping>

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="com.zll.test">
    <class name="Employee" table="employee">
        <id name="id">
            <generator class="native"></generator>
        </id>
        <property name="name" type="string" column="name"/>

        <!-- department属性,表达的是本类与Department的多对一 
            class属性:关联的实体类型
            column属性:外键列(引用关联对象的表的主键)
            外键方式必须维护关联关系的, 所有没有 inverse参数
        -->
        <many-to-one name="department" class="Department" column="departmentId" ></many-to-one>
    </class>
</hibernate-mapping>

测试:

package com.zll.test;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.junit.Test;

public class App {

    private static SessionFactory sessionFactory = new Configuration()//
            .configure()//
            .addClass(Department.class)// 添加Hibernate实体类(加载对应的映射文件)
            .addClass(Employee.class)// 添加Hibernate实体类(加载对应的映射文件)
            .buildSessionFactory();

    // 保存,有关联关系
    @Test
    public void testSave() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------

        // 新建对象
        Department department = new Department();
        department.setName("开发部");
        Employee employee1 = new Employee();
        employee1.setName("张三");
        Employee employee2 = new Employee();
        employee2.setName("李四");

        //第一种保存方式  员工关联部门  (少的一方维护关系)
        // 员工关联部门
        employee1.setDepartment(department);
        employee2.setDepartment(department);
        // 保存要注意顺序。
        // 由于员工持有关联关系,所以最好在员工插入前,先插入部门,否者会多执行两条 update 语句赵成资源的浪费。
        session.save(department);  
        session.save(employee1);
        session.save(employee2);


/*  不推荐的方式: 会多出两条 update语句
        //第二种保存方式   部门关联员工。(前提是 inverse=false 默认为false )
        //inverse 为false 表示主动维护关联关系
        department.getEmployees().add(employee1);
        department.getEmployees().add(employee2);

        // 由于部门主动维护关联关系,在插入数据过程如下:
        //1、部门首先会将自己持有的员工插入到数据库 2、在将自己查到到数据库 3 、在更新关联关系  
        //这样也会多出两条 update语句,不推荐使用。
        session.save(department); 
*/




        // --------------------------------------------
        session.getTransaction().commit();
        session.close();
    }

    // 获取,可以获取到关联的对方
    @Test
    public void testGet() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------

        // 获取一方,并显示另一方信息
        Department department = (Department) session.get(Department.class, 40);
        System.out.println(department);
        System.out.println(department.getEmployees());
         System.out.println("================================");
         Employee employee = (Employee) session.get(Employee.class, 87);
         System.out.println(employee);
         System.out.println(employee.getDepartment());


        // --------------------------------------------
        session.getTransaction().commit();
        session.close();
    }

    // 解除关联关系
    @Test
    public void testRemoveRelation() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------

        // // 从员工方解除
        // Employee employee = (Employee) session.get(Employee.class, 1);
        // employee.setDepartment(null);

        // 从部门方解除(与inverse有关系,为false时可以解除)
        Department department = (Department) session.get(Department.class, 3);
        department.getEmployees().clear();

        // --------------------------------------------
        session.getTransaction().commit();
        session.close();
    }

    // 删除对象,对关联对象的影响
    @Test
    public void testDelete() throws Exception {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // --------------------------------------------
        // // 删除员工方(多方),对对方没有影响
        // Employee employee = (Employee) session.get(Employee.class,2);
        // session.delete(employee);

        // 删除部门方(一方)
        // a, 如果没有关联的员工:能删除。
        // b, 如果有关联的员工且inverse=true,由于不能维护关联关系,直接执行删除,就会有异常
        // c, 如果有关联的员工且inverse=false,由于可以维护关联关系,他就会先把关联的员工的外键列设为null值,再删除自己。
        Department department = (Department) session.get(Department.class, 4);
        session.delete(department);
        // --------------------------------------------
        session.getTransaction().commit();
        session.close();
    }
}

cascade属性:级联操作。
默认为none,代表不级联。
级联是指操作主对象时,对关联的对象也做相同的操作。
可设为:delete, save-update, all, none …
举例:如果部门 cascade=delete 那么在删除部门时,会同时删除 所在部门的所有员工。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值