hibernate关联映射之一对多&多对一

Posted 码上加油站

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hibernate关联映射之一对多&多对一相关的知识,希望对你有一定的参考价值。

package loaderman.b_one2Many;

import java.util.HashSet;
import java.util.Set;

public class Dept {

    private int deptId;
    private String deptName;
    // 【一对多】 部门对应的多个员工
    private Set<Employee> emps = new HashSet<Employee>();

    public int getDeptId() {
        return deptId;
    }
    public void setDeptId(int deptId) {
        this.deptId = deptId;
    }
    public String getDeptName() {
        return deptName;
    }
    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }
    public Set<Employee> getEmps() {
        return emps;
    }
    public void setEmps(Set<Employee> emps) {
        this.emps = emps;
    }




}
package loaderman.b_one2Many;

public class Employee {

    private int empId;
    private String empName;
    private double salary;
    // 【多对一】员工与部门
    private Dept dept;


    public int getEmpId() {
        return empId;
    }
    public void setEmpId(int empId) {
        this.empId = empId;
    }
    public String getEmpName() {
        return empName;
    }
    public void setEmpName(String empName) {
        this.empName = empName;
    }
    public double getSalary() {
        return salary;
    }
    public void setSalary(double salary) {
        this.salary = salary;
    }
    public Dept getDept() {
        return dept;
    }
    public void setDept(Dept dept) {
        this.dept = dept;
    }


}
package loaderman.b_one2Many;

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

public class App1_save {

    private static SessionFactory sf;
    static {
        sf = new Configuration()
                .configure()
                .addClass(Dept.class)
                .addClass(Employee.class)   // 测试时候使用
                .buildSessionFactory();
    }

    // 保存, 部门方 【一的一方法操作】
    @Test
    public void save() {

        Session session = sf.openSession();
        session.beginTransaction();

        // 部门对象
        Dept dept = new Dept();
        dept.setDeptName("应用开发部");
        // 员工对象
        Employee emp_zs = new Employee();
        emp_zs.setEmpName("张三");
        Employee emp_ls = new Employee();
        emp_ls.setEmpName("李四");
        // 关系
        dept.getEmps().add(emp_zs);
        dept.getEmps().add(emp_ls);

        // 保存
        session.save(emp_zs);
        session.save(emp_ls);
        session.save(dept); // 保存部门,部门下所有的员工

        session.getTransaction().commit();
        session.close();
        /*
         *  结果
         *  Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
            Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
            Hibernate: insert into t_dept (deptName) values (?)
            Hibernate: update t_employee set deptId=? where empId=?    维护员工引用的部门的id
            Hibernate: update t_employee set deptId=? where empId=?
         */
    }
    // 【推荐】 保存, 部员方 【多的一方法操作】
    @Test
    public void save2() {

        Session session = sf.openSession();
        session.beginTransaction();

        // 部门对象
        Dept dept = new Dept();
        dept.setDeptName("综合部");
        // 员工对象
        Employee emp_zs = new Employee();
        emp_zs.setEmpName("张三");
        Employee emp_ls = new Employee();
        emp_ls.setEmpName("李四");
        // 关系
        emp_zs.setDept(dept);
        emp_ls.setDept(dept);


        // 保存
        session.save(dept); // 先保存一的方法
        session.save(emp_zs);
        session.save(emp_ls);// 再保存多的一方,关系会自动维护(映射配置完)

        session.getTransaction().commit();
        session.close();
        /*
         *  结果
         *  Hibernate: insert into t_dept (deptName) values (?)
            Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
            Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
            少生成2条update  sql
         */
    }

}
package loaderman.b_one2Many;

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


public class App2_get {

    private static SessionFactory sf;
    static {
        sf = new Configuration()
                .configure()
                .addClass(Dept.class)
                .addClass(Employee.class)   // 测试时候使用
                .buildSessionFactory();
    }

    @Test
    public void get() {

        Session session = sf.openSession();
        session.beginTransaction();

        // 通过部门方,获取另外一方
//        Dept dept = (Dept) session.get(Dept.class, 1);
//        System.out.println(dept.getDeptName());
//        System.out.println(dept.getEmps());// 懒加载


        // 通过员工房,获取另外一方
        Employee emp = (Employee) session.get(Employee.class, 1);
        System.out.println(emp.getEmpName());
        System.out.println(emp.getDept().getDeptName());


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

}
package loaderman.b_one2Many;

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


public class App3_inverse {

    private static SessionFactory sf;
    static {
        sf = new Configuration()
                .configure()
                .addClass(Dept.class)
                .addClass(Employee.class)   // 测试时候使用
                .buildSessionFactory();
    }

    // 1. 保存数据
    @Test
    public void save() {

        Session session = sf.openSession();
        session.beginTransaction();

        // 部门对象
        Dept dept = new Dept();
        dept.setDeptName("应用开发部");
        // 员工对象
        Employee emp_zs = new Employee();
        emp_zs.setEmpName("张三");
        Employee emp_ls = new Employee();
        emp_ls.setEmpName("李四");
        // 关系
        dept.getEmps().add(emp_zs);
        dept.getEmps().add(emp_ls);  // inverse=true,  不会设置关联。
        //                 此时的关联应该通过员工方维护。


        // 保存
        session.save(emp_zs);
        session.save(emp_ls);
        session.save(dept); // 保存部门,部门下所有的员工

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

    //2. 是否设置inverse,对获取数据的影响?   无.
    @Test
    public void get() {
        Session session = sf.openSession();
        session.beginTransaction();

        Dept dept = (Dept) session.get(Dept.class, 1);
        System.out.println(dept.getDeptName());
        System.out.println(dept.getEmps());

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

    // 3. 是否设置inverse,对解除关联关系影响?
    // inverse=false,  可以解除关联
    // inverse=true,  当前方(部门)没有控制权,不能解除关联关系(不会生成update语句,也不会报错)
    //
    @Test
    public void removeRelation() {
        Session session = sf.openSession();
        session.beginTransaction();

        // 获取部门
        Dept dept = (Dept) session.get(Dept.class, 2);
        // 解除关系
        dept.getEmps().clear();

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


    //3. 是否设置inverse属性,在删除数据中对关联关系的影响?
    // inverse=false, 有控制权, 可以删除。先清空外键引用,再删除数据。
    // inverse=true,  没有控制权: 如果删除的记录有被外键引用,会报错,违反主外键引用约束!
    //                             如果删除的记录没有被引用,可以直接删除。
    @Test
    public void deleteData() {
        Session session = sf.openSession();
        session.beginTransaction();

        // 查询部门
        Dept dept = (Dept) session.get(Dept.class, 8);
        session.delete(dept);


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









    @Test
    public void bak() {
        Session session = sf.openSession();
        session.beginTransaction();

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


}
package loaderman.b_one2Many;

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


public class App4_cascade {

    private static SessionFactory sf;
    static {
        sf = new Configuration()
                .configure()
                .addClass(Dept.class)
                .addClass(Employee.class)   // 测试时候使用
                .buildSessionFactory();
    }

    // 级联保存
    @Test
    public void save() {

        Session session = sf.openSession();
        session.beginTransaction();

        // 部门对象
        Dept dept = new Dept();
        dept.setDeptName("财务部");
        // 员工对象
        Employee emp_zs = new Employee();
        emp_zs.setEmpName("张三");
        Employee emp_ls = new Employee();
        emp_ls.setEmpName("李四");
        // 关系
        dept.getEmps().add(emp_zs);
        dept.getEmps().add(emp_ls);

        // 保存
//        session.save(emp_zs);
//        session.save(emp_ls);
        session.save(dept); // 需要设置级联保存; 保存部门,部门下所有的员工

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

    // 级联删除
    @Test
    public void delete() {
        Session session = sf.openSession();
        session.beginTransaction();

        Dept dept = (Dept) session.get(Dept.class,7);
        session.delete(dept); // 级联删除

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


    @Test
    public void bak() {
        Session session = sf.openSession();
        session.beginTransaction();

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


}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="loaderman.b_one2Many">
    
    <class name="Dept" table="t_dept">
        <id name="deptId">
            <generator class="native"></generator>
        </id>    
        <property name="deptName" length="20"></property>
        
        <!-- 
            一对多关联映射配置  (通过部门管理到员工)
            Dept 映射关键点:
            1.  指定 映射的集合属性: "emps"
            2.  集合属性对应的集合表: "t_employee"
            3.  集合表的外键字段   "t_employee. dept_id"
            4.  集合元素的类型
            
            inverse=false  set集合映射的默认值; 表示有控制权
         -->
         <set name="emps" cascade="save-update,delete" table="t_employee" inverse="true">   <!-- table="t_employee" -->
              <key column="dept_id"></key>
              <one-to-many class="Employee"/>
         </set>
         
         
    </class>
    

</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="loaderman.b_one2Many">
    
    <class name="Employee" table="t_employee">
        <id name="empId">
            <generator class="native"></generator>
        </id>    
        <property name="empName" length="20"></property>
        <property name="salary" type="double"></property>
        
        <!-- 
            多对一映射配置
            Employee 映射关键点:
            1.  映射的部门属性  :  dept
            2.  映射的部门属性,对应的外键字段: dept_id
            3.  部门的类型
         -->
         <many-to-one name="dept" column="dept_id" class="Dept"></many-to-one>
         
    </class>
    

</hibernate-mapping>

 

以上是关于hibernate关联映射之一对多&多对一的主要内容,如果未能解决你的问题,请参考以下文章

关联映射级联操作关系维护 ---- Hibernate之一对多|多对一关系

Hibernate,关系映射的多对一单向关联多对一双向关联一对一主键关联一对一外键关联多对多关系关联

1-7 hibernate关联关系映射

hibernate------映射相关

Hibernate的关联关系映射

hibernate映射的 关联关系:有 一对多关联关系,一对一关联关系,多对多关联关系,继承关系