• hibernate 关系映射


        首先,我们知道hibernate是一个ORM框架,ORM的全称是(Object Relational Mapping),既对象关系映射,那么hibernate有几种对象关系映射呢?接下来我们来一一举例出

        Hibernate在实现ORM功能的时候主要用到的文件有:映射类(*.java)、映射文件(*.hbm.xml)和数据库配置文件(*hibernate.cfg.xml)

        编写 Emp类

            

         编写Dept类

      

    1.多对一关联映射(many-to-one):

    接下来,我们来编写实体类的映射文件

    /*
      *查询员工所在的部门,多对一关系
      * */
      @Test
    public void test01(){
          /*调用HibernateUtil工具类的getSession()方法获取session*/
          Session session = HibernateUtil.getSession();
          /*延迟加载出员工对象*/
          Emp emp = session.load(Emp.class, 1);
          /*输出员工所在的部门名称*/
          System.out.println(emp.getDept().getDeptname());
    
      }
    
    /*
    * 多对一单项关联
    * */
    @Test
     public  void testmanytoone(){
         /*调用HibernateUtil工具类的getSession()方法获取session*/
        Session session = HibernateUtil.getSession();
        /*创建Transaction事务*/
        Transaction tr=session.beginTransaction();
           /*创建部门对象*/
        Dept dept=new Dept();
        dept.setDeptname("发财二部");
         /*创建员工对象*/
        Emp emp=new Emp();
        emp.setEmpname("许先生");
        /*将dept对象放入员工Emp对象中*/
        emp.setDept(dept);
        session.save(dept);
        session.save(emp);
          /*提交事务*/
        tr.commit();
    }
    
    @Test
    /*
    * 按照指定的部门编号查询对应的员工信息
    * */
    public void test3(){
         /*调用HibernateUtil工具类的getSession()方法获取session*/
        Session session = HibernateUtil.getSession();
        /*创建Transaction事务*/
        Transaction tx=session.beginTransaction();
        /*编写hql语句,按照指定的部门编号查询对应的员工信息*/
        String hql="from Emp e where e.dept.deptno=1";
         /*将生成的Bean为query对象装入list*/
        Query query = session.createQuery(hql);
        List<Emp> list = query.list();
        /*输出对应的部门的员工名称*/
        for (Emp item : list) {
            System.out.println(item.getEmpname());
        }
        tx.commit();
    }
    /*查询所有的员工和各自对应的部门*/
    @Test
    public void test4(){
      /*调用HibernateUtil工具类的getSession()方法获取session*/
        Session session = HibernateUtil.getSession();
         /*创建Transaction事务*/
        Transaction tr =session.beginTransaction();
        /*编写hql,查询所以员工*/
        String hql="from Emp";
         /*将生成的Bean为query对象装入list*/
        Query query = session.createQuery(hql);
        List<Emp> list = query.list();
        /*输出所以员工和每个员工对应的部门*/
        for (Emp emp:list) {
            System.out.println(emp.getDept().getDeptname());
            System.out.println(emp.getEmpname()+"----------------"+emp.getEmpno());
        }
    }
     /*修改员工的部门编号*/
     @Test
    public  void  test5(){
         Session session = HibernateUtil.getSession();
         Transaction tr =session.beginTransaction();
         Emp emp = session.load(Emp.class, 1);
         Dept dept = session.load(Dept.class, 2);
         emp.setDept(dept);
         tr.commit();
     }

     2. 一对多关联映射(one-to-many):


    这个时候我们需要在Dept实体加入Set集合

    那么为什么要用set集合而不用list呢
     首先,你要清楚List和Set的区别:List是有序和可重复;Set是无序,但是不能重复.
    其次,在一对多关联中.想象一下这种情况:你要更新从表记录;
    从List中得到从表的一个对象引用,然后你对这样对象修改后,又放回List,你的List中就包括两个从表对象的引用.你在保存时,这两个引用,你觉得会保存两次还是一次?
    而如果是Set,你得到从表对象的引用,之后修改从表对象的内容,你再往Set里面放,Set里面因为已经有这个从表对象的引用,就不会再给里面加.这样,你的Set里面还是只有一个从表对象的引用.这样你保存,这个从表对象只保存一次.

    映射文件 Dept.hbm.xml
     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="cn.hibernate.day04.entity">
     6     <!--实体 name=实体端的内容   column=DB端的内容-->
     7     <class name="Dept" table="DEPT">
     8         <!--和底层数据表对应的主键   业务意义-->
     9         <id name="deptno" column="DEPTNO">
    10            <generator class="native"></generator>
    11         </id>
    12         <property name="deptname" column="DEPTNAME" length="32"></property>
    13         <!--一对多-->
    14         <set name="emps" cascade="save-update,persist" table="Emp" >
    15             <key column="deptno"></key>
    16             <one-to-many class="Emp"></one-to-many>
    17         </set>
    18     </class>
    19 </hibernate-mapping>


    接下来是列子
      /*查询所有的部门,并把部门所对应的员工信息检索出来,一对多关系*/
    @Test
     public void testonetomany(){
        /*编写hql语句:查询所有部门*/
         String hql="from Dept";
         /*调用HibernateUtil工具类的getSession()方法获取session*/
        Session session = HibernateUtil.getSession();
        /*将生成的Bean为query对象装入list*/
        Query query =  session.createQuery(hql);
        List<Dept> list = query.list();
        /*遍历部门输出部门名称*/
        for (Dept dept:list) {
            System.out.println(dept.getDeptname()+"--------------");
            /*根据部门实体中的Set集合获取员工信息,遍历输出*/
            for (Emp emp:dept.getEmps()) {
                System.out.println(emp.getEmpname()+"--------------");
            }
        }
    }
    
    
    /*添加部门和员工信息,一对多关系*/
    @Test
     public  void  testsaveDept(){
         /*调用HibernateUtil工具类的getSession()方法获取session*/
        Session session = HibernateUtil.getSession();
        /*创建Transaction事务*/
        Transaction tx=session.beginTransaction();
        /*创建部门对象*/
        Dept dept=new Dept();
        dept.setDeptname("财务部");
        /*创建员工对象*/
        Emp emp=new Emp();
        emp.setEmpname("笑醒");
        /*调用add()方法将emp对象放入dept,如果不写,添加的时候不会添加员工信息*/
        dept.getEmps().add(emp);
        session.save(dept);
        /*提交事务*/
        tx.commit();
    }


      注意:它与多对一的区别是维护的关系不同

              *多对一维护的关系是:多指向一的关系,有了此关系,加载多的时候可以将一加载上来
              *一对多维护的关系是:一指向多的关系,有了此关系,在加载一的时候可以将多加载上来

    3.多对多单向关联(many-to-many)

      首先我们需要两个拥有多对多关系的类,生活中多对多关系的列子很多,随便就能列出了,比如学生和老师,程序员和项目,那么我们用程序员员工和项目来做列子

    //员工实体
    public class Employee {
        private Integer empid;
        private String empname;
        private Set<Project> projects = new HashSet<Project>();
    }
    /**
     * Created by Happy on 2017-09-26.
     * 工程实体
     */
    public class Project {
        private Integer proid;
        private String proname;
        private Set<Employee> employees=new HashSet<Employee>();

    接下来我们来写两个配置文件

    Project.hbm.xml

    <?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="cn.hibernate.day05.entity">
        <!--实体 name=实体端的内容   column=DB端的内容-->
        <class name="Project" table="PROJECT">
            <!--和底层数据表对应的主键   业务意义-->
            <id name="proid" column="PROID">
               <generator class="native"></generator>
            </id>
            <property name="proname" column="PRONAME" length="32"></property>
        </class>
    </hibernate-mapping>

    Employee.hbm.xml

    <?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="cn.hibernate.day05.entity">
        <!--实体 name=实体端的内容   column=DB端的内容-->
        <class name="Employee" table="EMPLOYEE">
            <!--和底层数据表对应的主键   业务意义-->
            <id name="empid" column="EMPID">
               <generator class="native"></generator>
            </id>
            <property name="empname" column="EMPNAME" length="32"></property>
            <!--
              Table属性:中间表(集合表)
              key子元素:集合外键(引用当前表主键的外键),里面的Column指的是在中间表中的列名
              many-to-many子元素:里面的class属性是指关联的类型,column是指引用Project的主键值
          -->
            <set name="projects" cascade="save-update" table="EMPPRO" >
                <key column="EPMRID"></key>
                <many-to-many class="Project" column="RPROID"></many-to-many>
            </set>
        </class>
    </hibernate-mapping>

    接下来是测试列子

      /*添加多对多单向关联信息*/
        @Test
        public  void  test01(){
             /*调用HibernateUtil工具类的getSession()方法获取session*/
            Session session=HibernateUtil.getSession();
             /*创建Transaction事务*/
            Transaction tx=session.beginTransaction();
              /*创建员工对象*/
            Employee emp1=new Employee();
            emp1.setEmpname("没事了大疯狂拉升");
            /*创建项目对象*/
            Project pro1=new Project();
            pro1.setProname("海淀花园");
            Project pro2=new Project();
            pro2.setProname("海上花园");
            emp1.getProjects().add(pro1);
            emp1.getProjects().add(pro2);
            session.save(emp1);
            session.save(pro1);
            session.save(pro2);
            tx.commit();
        }
    
        /*查询项目Set集合中对象的个数*/
         @Test
        public  void  test02(){
             Session session = HibernateUtil.getSession();
             Transaction transaction = session.beginTransaction();
             Employee employee = session.load(Employee.class, 1);
             Set<Project> projects=employee.getProjects();
             System.out.println(projects.size());
    
         }

    4.多对多双向关联(many-tomany)

    需要在Project.hbm.xml加入set

    <?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="cn.hibernate.day05.entity">
        <!--实体 name=实体端的内容   column=DB端的内容-->
        <class name="Project" table="PROJECT">
            <!--和底层数据表对应的主键   业务意义-->
            <id name="proid" column="PROID">
               <generator class="native"></generator>
            </id>
            <property name="proname" column="PRONAME" length="32"></property>
            <set name="employees" table="EMPPRO" >
                <key column="RPROID" ></key>
                <many-to-many column="EPMRID" class="Employee" ></many-to-many>
            </set>
        </class>
    </hibernate-mapping>

    测试类

      /*添加多对多单向关联信息*/
        @Test
        public  void  test01(){
             /*调用HibernateUtil工具类的getSession()方法获取session*/
            Session session=HibernateUtil.getSession();
             /*创建Transaction事务*/
            Transaction tx=session.beginTransaction();
              /*创建员工对象*/
            Employee emp1=new Employee();
            emp1.setEmpname("没事了大疯狂拉升");
            /*创建项目对象*/
            Project pro1=new Project();
            pro1.setProname("海淀花园");
            Project pro2=new Project();
            pro2.setProname("海上花园");
            emp1.getProjects().add(pro1);
            emp1.getProjects().add(pro2);
            session.save(emp1);
           /* session.save(pro1);
            session.save(pro2);*/
            tx.commit();
        }

    关联关系中常用属性

    1.级联(cascade)

     我们以部门和员工的关系为例讲解一对多关联关系映射时,删除部门时,如果部门有关联的员工且inverse属性为false,那么由于可以维护关联关系,它就会先把关联的员工的外键列设为null值,再删除自己。但是此刻希望删除部门时,就附带着把该部门下的所有员工都删掉,这时就需要引入cascade属性了。

    当Hibernate持久化一个临时对象时,在默认情况下,它不会自动持久化所关联的其他临时对象,而是会抛出TransientObjectException。如果设定many-to-one元素的cascade属性为save-update的话,可实现自动持久化所关联的对象。如:

    2. set元素的inverse属性

     inverse有两属性:

    1 .false    设置为false,则为主动方,由主动方负责维护关联关系,默认是false

    2 .true    设置为true,则不为主动方,并且不负责维护关联关系,而是由不包含这个关系的一方来维护这个关系

    3.order_by     其作用就是对集合中的数据进行排序

  • 相关阅读:
    Java并发编程:CountDownLatch、CyclicBarrier和Semaphore (总结)
    Java线程面试题 Top 50 (个人总结)(转)
    rabbitMQ windows 安装 入门(转)
    Java并发编程:volatile关键字解析(学习总结-海子)
    关于Sychronized和volatile自己总结的一点点理解(草稿)
    FWORK-数据存储篇 -- 范式与反模式 (学习和理解)
    Synchronized的原理及自旋锁,偏向锁,轻量级锁,重量级锁的区别(摘抄和理解)
    vcfc之zk+postsql+keystore(cassandra)框架分析
    CAP理论-解析
    java多线程通信 例子
  • 原文地址:https://www.cnblogs.com/xuhaifeng017/p/8136981.html
Copyright © 2020-2023  润新知