Hibernate之關聯關系映射(一對多和多對一映射,多對多映射)


~~~接着之前的Hibernate框架接着學習(上篇面試過后發現真的需要學習一下框架了,不然又被忽悠讓去培訓。)~~~

1:Hibernate的關聯映射,存在一對多和多對一映射,多對多映射:

  1.1:一對多和多對一映射,舉例說明:

     學生和老師:

       一個老師可以教多個學生 【一對多映射】

      多個學生可以被一個老師教【多對一映射】

    部門與員工:

      一個部門有多個員工【一對多映射】

      多個員工屬於一個部門【多對一映射】

  1.2:多對多,舉例說明:

    項目和開發員工:【雙向一對多即多對多映射】

      一個項目有多個開發人員【一對多】

         一個開發人員參與多個項目【一對多】


2:一對多和多對一映射,理清以下思路就可以進行簡單的開發了:

  2.1:首先導入hibernate框架所需要的包哦~~~

  2.2:由於是在hibernate.cfg.xml配置里面自動生成數據庫和表,所以不用手動創建了

  2.3:進入正題,開發創建實體類;下面是兩個實體類的關鍵點;

    Dept.java:

      注意private Set<Employee> emps;//部門對應多個員工,即一對多的關系

    Employee.java:

      private Dept dept;//員工和部門的關系

 1 package com.bie.po;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 /** 
 7 * @author BieHongLi 
 8 * @version 創建時間:2017年3月20日 上午9:45:21 
 9 * 部門的實體類
10 *     關鍵點,是通過部門實體類維護到員工的實體類
11 */
12 public class Dept {
13 
14     private int deptId;//部門編號
15     private String deptName;//部門名稱
16     
17     private Set<Employee> emps;//部門對應多個員工,即一對多的關系
18     //private Set<Employee> emps = new HashSet<>();//方便賦值,這里可以直接創建實例化
19     
20     
21     public int getDeptId() {
22         return deptId;
23     }
24     public void setDeptId(int deptId) {
25         this.deptId = deptId;
26     }
27     public String getDeptName() {
28         return deptName;
29     }
30     public void setDeptName(String deptName) {
31         this.deptName = deptName;
32     }
33     public Set<Employee> getEmps() {
34         return emps;
35     }
36     public void setEmps(Set<Employee> emps) {
37         this.emps = emps;
38     }
39     
40     
41 }
View Code
 1 package com.bie.po;
 2 /** 
 3 * @author BieHongLi 
 4 * @version 創建時間:2017年3月20日 上午9:46:45 
 5 * 員工的實體類
 6 */
 7 public class Employee {
 8 
 9     private int empId;//員工的編號
10     private String empName;//員工的名稱
11     private double salary;//員工的薪資
12     
13     private Dept dept;//員工和部門的關系
14     
15     public int getEmpId() {
16         return empId;
17     }
18     public void setEmpId(int empId) {
19         this.empId = empId;
20     }
21     public String getEmpName() {
22         return empName;
23     }
24     public void setEmpName(String empName) {
25         this.empName = empName;
26     }
27     public double getSalary() {
28         return salary;
29     }
30     public void setSalary(double salary) {
31         this.salary = salary;
32     }
33     public Dept getDept() {
34         return dept;
35     }
36     public void setDept(Dept dept) {
37         this.dept = dept;
38     }
39     
40     
41 }
View Code

  2.4:創建好實體類就可以進行創建hibernate的映射文件了,如Dept.hbm.xml和Employee.hbm.xml映射文件;

     部門表進行映射的時候:

      需要注意使用set集合進行映射的注意點:

Dept映射關鍵點:
1:指定映射的集合屬性:"emps"
2:集合屬性對應的集合表:"20171021_employee"
3:集合表的外鍵字段"20171021_employee.deptId"
4:集合元素的類型

    員工表進行映射的時候:

      需要注意<many-to-one name="dept" column="deptId" class="Dept"></many-to-one>

      將一個對象映射成為外鍵字段,只能使用many-to-one這個配置。

Employee映射關鍵點:
1:映射的部門屬性:dept
2:映射的部門對象,對應的外鍵字段:dept_id
3:指定部門的類型

 

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5     
 6 <!-- 如果hibernate-mapping的package屬性直接初始化了,下面就可以直接引用了 -->    
 7 <hibernate-mapping package="com.bie.po">
 8     <class name="Dept" table="dept">
 9         <!-- 第一首先寫主鍵映射 -->
10         <id name="deptId" column="deptId">
11             <generator class="native"></generator>
12         </id>
13         <!-- 第二寫非主鍵映射 -->
14         <property name="deptName" column="deptName" length="20" type="string"></property>
15     
16         <!-- 
17             第三寫其他映射,比如這里的set集合映射, 
18         -->
19         <!-- 
20             一對多關聯映射配置(通過部門管理到員工)
21             Dept映射關鍵點
22                 (1)指定映射的集合屬性:""emps;
23                 (2)集合屬性對應的集合表:"employee";
24                 (3)集合表的外鍵字段:employee.empId        
25                 (4)集合元素的類型
26          -->
27         <!-- name指定了映射的集合的屬性,即集合實例化的emps;table指定了集合屬性對應的集合表 -->        
28         <set name="emps" table="employee">
29             <!--column指定了集合表的外鍵  -->
30             <key column="deptId"></key>
31             <!-- class由於上面已經寫了包名,這里直接使用即可 -->
32             <one-to-many class="Employee"/>
33         </set>
34     </class>
35 </hibernate-mapping>
36     
37     
38     
 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5 <!-- 這里指定package,里面就可以直接引用了 -->
 6 <hibernate-mapping package="com.bie.po">
 7     <class name="Employee" table="employee">
 8         <!-- 1:主鍵映射 -->
 9         <id name="empId" column="empId">
10             <generator class="native"></generator>
11         </id>
12         
13         <!-- 2:非主鍵映射 -->
14         <property name="empName" column="empName" length="20" type="string"></property>
15         <property name="salary" column="salary" type="double"></property>
16         
17         <!--
18              多對一的映射配置;Employee映射的關鍵點
19              (1)映射的部門屬性:dept
20              (2)映射的部門對新,對應的外鍵字段:deptId
21              (3)部門的類型:Dept
22          -->
23          <many-to-one name="dept" column="deptId" class="Dept"></many-to-one>
24     </class>
25 
26 </hibernate-mapping>    
27     
28     

  2.5:配置好映射文件,就可以配置hibernate的配置文件了,hibernate.cfg.xml;

    注意:

      第二部分其他配置的時候注意顯示sql語句和方言還有自動創建數據表這些細節問題

      第三部分加載映射文件的寫法也需要注意

 1 <!DOCTYPE hibernate-configuration PUBLIC
 2     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 3     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 4     
 5 <hibernate-configuration>
 6     <session-factory>
 7         <!-- 第一部分:連接數據庫的操作,加載驅動,連接數據庫的url和賬號密碼 -->
 8         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
 9         <property name="hibernate.connection.url">jdbc:mysql:///test</property>
10         <property name="hibernate.connection.username">root</property>
11         <property name="hibernate.connection.password">123456</property>
12     
13         <!-- 第二部分:其他相關配置 -->
14         <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
15         <property name="hibernate.show_sql">true</property>
16         <property name="hibernate.format_sql">true</property>
17         <property name="hibernate.hbm2ddl.auto">update</property>
18         <!-- <property name="hibernate.hbm2ddl.auto">create</property> -->
19         
20         <!-- 第三部分:加載映射文件 -->
21         <mapping resource="com/bie/po/Dept.hbm.xml"/>
22         <mapping resource="com/bie/po/Employee.hbm.xml"/>
23     </session-factory>
24 </hibernate-configuration>

  2.6:最后就可以使用junit進行測試了,如下所示:

    (1)首先清楚下面兩種測試的區別是是否在實體類實例化set集合

        private Set<Employee> emps;//部門對應多個員工,即一對多的關系
          private Set<Employee> emps = new HashSet<>();//方便賦值,這里可以直接創建實例化

    (2)下面兩種情況都可以設置好部門和員工的信息。就是在配置映射的時候一定搞清楚set集合映射的配置和many-to-one的配置

       I:從部門的一方設置員工的信息【不推薦】 

         dept.getEmps().add(emp1);
               dept.getEmps().add(emp2);
      
            II:從員工的一方設置好部門的信息【推薦,在一對多和多對一的關聯關系中,保存數據最好是通過多對一來維護關系,這樣可以減少update語句的生成,從而提高hibernate的利用效率】
              emp1.setDept(dept);
              emp2.setDept(dept);

    (3)最后是保存的順序,保存的順序最好是先保存一的一方再保存多的一方,這樣可以提高效率,少執行sql語句

        第一種方法(推薦)

session.save(dept);//先保存一的一方
session.save(emp1);
session.save(emp2);//再保存多的一方,關系會自動維護(但是映射配置必須配置好的 )
                  

        第二種方法(不推薦)

session.save(emp1);//先保存多的一方,關系會自動維護(但是映射配置必須配置好的 )
session.save(emp2);
session.save(dept);//保存一的一方

  1 package com.bie.test;
  2 
  3 import java.util.HashSet;
  4 import java.util.Set;
  5 
  6 import org.hibernate.Session;
  7 import org.hibernate.SessionFactory;
  8 import org.hibernate.cfg.Configuration;
  9 import org.junit.Test;
 10 
 11 import com.bie.po.Dept;
 12 import com.bie.po.Employee;
 13 
 14 /** 
 15 * @author BieHongLi 
 16 * @version 創建時間:2017年3月20日 上午10:29:38 
 17 * 
 18 */
 19 public class OneManyTest {
 20 
 21     //初始化靜態的session工廠
 22     private static SessionFactory sf = null;
 23     static{
 24         //這里使用簡寫的方法,首先加載默認的hibernate.cfg.xml,然后是創建session工廠
 25         sf = new Configuration().configure().buildSessionFactory();
 26     }
 27     
 28     @Test
 29     public void test(){
 30         //創建session,import org.hibernate.Session;
 31         Session session = sf.openSession();
 32         //session開始事務
 33         session.beginTransaction();
 34         
 35         //1:關鍵點,部門對象的初始化,創建一個部門
 36         Dept dept = new Dept();
 37         dept.setDeptName("開發部");
 38         
 39         //2:關鍵點,員工的初始化,創建兩個人對象
 40         Employee emp1 = new Employee();
 41         emp1.setEmpName("張三");
 42         Employee emp2 = new Employee();
 43         emp2.setEmpName("李四");
 44         
 45         //3:然后將創建的人添加到set集合中
 46         Set<Employee> set = new HashSet<>();
 47         set.add(emp1);
 48         set.add(emp2);
 49         
 50         //4:再將set集合中保存的人保存到部門里面
 51         dept.setEmps(set);
 52         
 53         //5:最后保存員工對象,部門
 54         session.save(emp1);
 55         session.save(emp2);
 56         session.save(dept);
 57         
 58         //提交事務,省去了事務new實例化了
 59         session.getTransaction().commit();
 60         //關閉session
 61         session.close();
 62     }
 63     
 64     @Test
 65     public void test2(){
 66         //創建session,import org.hibernate.Session;
 67         Session session = sf.openSession();
 68         //session開始事務
 69         session.beginTransaction();
 70         
 71         //1:關鍵點,部門對象的初始化,創建一個部門
 72         Dept dept = new Dept();
 73         dept.setDeptName("研發部2");
 74         
 75         //2:關鍵點,員工的初始化,創建兩個人對象
 76         Employee emp1 = new Employee();
 77         emp1.setEmpName("小三子2");
 78         Employee emp2 = new Employee();
 79         emp2.setEmpName("小四子2");
 80         
 81         //3:再將set集合中保存的人保存到部門里面
 82         //dept.getEmps().add(emp1);
 83         //dept.getEmps().add(emp2);
 84         
 85         //或者是從員工的一方設置好部門的信息
 86         emp1.setDept(dept);
 87         emp2.setDept(dept);
 88         
 89         //4:最后保存員工對象,部門,保存的順序也會影響sql語句的,所以最好先保存一的一方
 90         session.save(dept);//先保存一的一方
 91         session.save(emp1);
 92         session.save(emp2);//再保存多的一方,關系會自動維護(但是映射配置必須配置好的 )
 93         
 94         //提交事務,省去了事務new實例化了
 95         session.getTransaction().commit();
 96         //關閉session
 97         session.close();
 98     }
 99     
100 }

測試結果如下所示(由於set集合在實體類里面初始化和不初始化出現下面兩種情況,所以需要注意兩種測試測試的方法):


 3:多對多映射,這個需要理解清楚他們之間的關系。不然很容易搞混亂的。

  3.1:創建實體類:

    Project.java

      項目下面的多個員工
        private Set<Develope> deve = new HashSet<Develope>();

     Develope.java

     開發人員參入的多個項目
         private Set<Project> project = new HashSet<Project>(); 

 1 package com.bie.domain;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 /** 
 7 * @author BieHongLi 
 8 * @version 創建時間:2017年3月20日 下午5:32:42 
 9 * 項目的實體類
10 */
11 public class Project {
12 
13     private int proId;
14     private String proName;
15     
16     //項目下面的多個員工
17     private Set<Develope> deve = new HashSet<Develope>();
18 
19     public int getProId() {
20         return proId;
21     }
22     public void setProId(int proId) {
23         this.proId = proId;
24     }
25     public String getProName() {
26         return proName;
27     }
28     public void setProName(String proName) {
29         this.proName = proName;
30     }
31     public Set<Develope> getDeve() {
32         return deve;
33     }
34     public void setDeve(Set<Develope> deve) {
35         this.deve = deve;
36     }
37     
38 }
View Code
 1 package com.bie.domain;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 /** 
 7 * @author BieHongLi 
 8 * @version 創建時間:2017年3月20日 下午5:33:53 
 9 * 項目參入人員
10 */
11 public class Develope {
12 
13     private int deveId;
14     private String deveName;
15     
16     //開發人員參入的多個項目
17     private Set<Project> project = new HashSet<Project>();
18 
19     public int getDeveId() {
20         return deveId;
21     }
22     public void setDeveId(int deveId) {
23         this.deveId = deveId;
24     }
25     public String getDeveName() {
26         return deveName;
27     }
28     public void setDeveName(String deveName) {
29         this.deveName = deveName;
30     }
31     public Set<Project> getProject() {
32         return project;
33     }
34     public void setProject(Set<Project> project) {
35         this.project = project;
36     }
37     
38     
39 }
View Code

  3.2:如上面的,創建好實體類就可以配置就可以配置映射文件了:【注意,主鍵一定設置自增,開始我沒寫,報錯了哦~~~】

    Project.hbm.xml:【關鍵點】

      <!-- 實體類set集合實例化的對象name和中間表table -->
             <set name="deve" table="relation">
                <!-- 設置項目的主鍵 -->
                <key column="proId"></key>
                <!-- 設置人員的主鍵作為中間表的外鍵和人員對應的實體類 -->
                <many-to-many column="deve_Id" class="Develope"></many-to-many>
            </set>

    Develope.hbm.xml:【關鍵點】

      <set name="project" table="relation">
                <key column="deveId"></key>
                <many-to-many column="proId" class="Project"></many-to-many>
             </set>

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5 
 6 <hibernate-mapping package="com.bie.domain">
 7     <class name="Project" table="project">
 8         <!-- 主鍵映射 -->
 9         <id name="proId" column="proId">
10             <generator class="native"></generator>
11         </id>
12         <!-- 非主鍵映射 -->
13         <property name="proName" column="proName" type="string" length="20"></property>
14         
15         <!-- 其他映射配置 -->
16         <!-- 
17             多對多映射:
18                 1:映射的集合屬性:deve
19                 2:集合屬性,對應的中間表:relation
20                 3:外鍵字段:proId
21                 4:外鍵字段,對應的中間表字段:deveId
22                 5:集合屬性元素的類型
23         
24          -->
25         <!-- 實體類set集合實例化的對象name和中間表table -->
26           <set name="deve" table="relation">
27               <!-- 設置項目的主鍵 -->
28               <key column="proId"></key>
29               <!-- 設置人員的主鍵作為中間表的外鍵和人員對應的實體類 -->
30               <many-to-many column="deve_Id" class="Develope"></many-to-many>
31           </set> 
32          
33     </class>
34     
35 </hibernate-mapping>    
36     
37     
 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC 
 3     "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 4     "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
 5 <hibernate-mapping package="com.bie.domain">
 6     <class name="Develope" table="develope">
 7         <!-- 主鍵映射 -->
 8         <id name="deveId" column="deveId">
 9             <generator class="native"></generator>
10         </id>
11         <!-- 非主鍵映射 -->
12         <property name="deveName" column="deveName"></property>
13         
14         <!-- 其他映射配置 -->
15         <!-- 
16             多對多映射:員工方
17                 1:映射的集合屬性:project
18                 2:集合屬性,對應的中間表:relation
19                 3:外鍵字段:deveId
20                 4:外鍵字段,對應的中間表字段:proId
21                 5:集合屬性元素的類型
22          -->
23         <set name="project" table="relation">
24             <key column="deveId"></key>
25             <many-to-many column="proId" class="Project"></many-to-many>
26         </set> 
27         
28     </class>
29 
30 </hibernate-mapping>
31     
32     

  3.3:這里配置Hibernate.cfg.xml,和上面的配置類似。

   <!-- 第三部門:多對多映射的映射加載文件 -->
        <mapping resource="com/bie/domain/Project.hbm.xml"/>
        <mapping resource="com/bie/domain/Develope.hbm.xml"/>

 1 <!DOCTYPE hibernate-configuration PUBLIC
 2     "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 3     "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 4     
 5 <hibernate-configuration>
 6     <session-factory>
 7         <!-- 第一部分:連接數據庫的操作,加載驅動,連接數據庫的url和賬號密碼 -->
 8         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
 9         <property name="hibernate.connection.url">jdbc:mysql:///test</property>
10         <property name="hibernate.connection.username">root</property>
11         <property name="hibernate.connection.password">123456</property>
12     
13         <!-- 第二部分:其他相關配置 -->
14         <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
15         <property name="hibernate.show_sql">true</property>
16         <!-- <property name="hibernate.format_sql">true</property> -->
17         <property name="hibernate.hbm2ddl.auto">update</property> 
18         <!-- <property name="hibernate.hbm2ddl.auto">create</property> -->
19         
20         <!-- 第三部分:加載映射文件 -->
21         <mapping resource="com/bie/po/Dept.hbm.xml"/>
22         <mapping resource="com/bie/po/Employee.hbm.xml"/>
23         
24         
25         <!-- 第三部門:多對多映射的映射加載文件 -->
26         <mapping resource="com/bie/domain/Project.hbm.xml"/>
27         <mapping resource="com/bie/domain/Develope.hbm.xml"/>
28         
29     </session-factory>
30 </hibernate-configuration>
View Code

  3.4:最后測試就可以了,多對多的關系映射:

 1 package com.bie.test;
 2 
 3 import org.hibernate.Session;
 4 import org.hibernate.SessionFactory;
 5 import org.hibernate.cfg.Configuration;
 6 import org.junit.Test;
 7 
 8 import com.bie.domain.Develope;
 9 import com.bie.domain.Project;
10 
11 /** 
12 * @author BieHongLi 
13 * @version 創建時間:2017年3月20日 下午7:27:00 
14 * 多對多的測試
15 */
16 public class Many2ManyTest {
17 
18     public static SessionFactory sf =null;
19     static{
20         sf = new Configuration().configure().buildSessionFactory();
21     }
22     
23     @Test
24     public void test(){
25         Session session = sf.openSession();
26         session.beginTransaction();
27         
28         //創建項目和員工進行保存測試
29         Project pro1 = new Project();
30         pro1.setProName("企業費用管理系統");
31         Project pro2 = new Project();
32         pro2.setProName("企業辦公系統");
33         
34         Develope dev1 = new Develope();
35         dev1.setDeveName("張三");
36         Develope dev2 = new Develope();
37         dev2.setDeveName("李四");
38         Develope dev3 = new Develope();
39         dev3.setDeveName("王五");
40         
41         //設置關系,
42         pro1.getDeve().add(dev1);
43         pro1.getDeve().add(dev2);
44         pro2.getDeve().add(dev1);
45         pro2.getDeve().add(dev3);
46         
47         //保存到session中,保存員工和項目到session中
48         session.save(dev1);
49         session.save(dev2);
50         session.save(dev3);
51 
52         session.save(pro1);
53         session.save(pro2);
54         
55         //提交
56         session.getTransaction().commit();
57         session.close();
58     }
59     
60 }

只有學習才能使我快樂~~~,加油~~~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM