• 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 }

    只有学习才能使我快乐~~~,加油~~~

  • 相关阅读:
    如何把两个查询语句合成一条 语句
    SpringBoot之springfox(Swagger) (ApiDoc接口文档)
    springboot + swagger
    高等数学(上)第2章——导数与微分
    oracle 常用 sql
    线性代数基础知识(三)—— 矩阵乘法
    Neo4j(一)
    医学知识图谱(二)——应用
    医学知识图谱一
    数学基本概念
  • 原文地址:https://www.cnblogs.com/biehongli/p/6561690.html
Copyright © 2020-2023  润新知