1. 程式人生 > >hibernate關聯對映之一對多&多對一

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>