• Hibernate框架之关联映射入门


    关联映射就是将关联关系映射到数据库里,在对象模型中就是一个或多个引用。

    一:配置单向多对一关联

     在Emp类中定义一个Dept属性,而在Dept类中无须定义用于存放Emp对象的集合属性

     01.Dept.java

    package cn.zhang.entity;
    
    //部门实体类
    public class Dept {
        
        private Integer deptid;//编号
        
        private String deptname;//名称
    
    
        public Integer getDeptid() {
            return deptid;
        }
    
        public void setDeptid(Integer deptid) {
            this.deptid = deptid;
        }
    
        public String getDeptname() {
            return deptname;
        }
    
        public void setDeptname(String deptname) {
            this.deptname = deptname;
        }
    
    }

    02.Emp.java

    package cn.zhang.entity;
    //员工实体类
    public class Emp {
        
        private Integer empno;//编号
        
        private String empname;//姓名
        
        private Dept dept;//所属部门
        
    
        public Dept getDept() {
            return dept;
        }
    
        public void setDept(Dept dept) {
            this.dept = dept;
        }
    
        public Integer getEmpno() {
            return empno;
        }
    
        public void setEmpno(Integer empno) {
            this.empno = empno;
        }
    
        public String getEmpname() {
            return empname;
        }
    
        public void setEmpname(String empname) {
            this.empname = empname;
        }
        
    }

    03.Dept.hbm.xml

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="cn.zhang.entity">
    <class name="Dept" table="DEPT">
    <!--主键生成策略-->
    <id name="deptid" column="DEPTID">
       <generator class="sequence">
       <param name="sequence">SQ_Num</param>
       </generator>
    </id>
    <property name="deptname" type="string" column="deptname"/>
    </class>
    </hibernate-mapping>

    04.Emp.hbm.xml

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="cn.zhang.entity">
    <class name="Emp" table="EMP">
    <!-- 主键生成策略 -->
    <id name="empno" column="empno">
        <generator class="sequence">
       <param name="sequence">SQ_Num</param>
       </generator>
    </id>
    <property name="empname" type="string" column="empname"/>
    <!-- 多对一(员工对部门) -->
     <many-to-one name="dept" column="deptid" class="Dept"></many-to-one> 
    </class>
    </hibernate-mapping>

    05.hibernate.cfg.xml  配置文件

    <?xml version='1.0' encoding='utf-8'?>
    <!DOCTYPE hibernate-configuration PUBLIC
            "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
    
    <hibernate-configuration>
    
        <session-factory>
    
            <!-- Database connection settings -->
            <property name="connection.driver_class">oracle.jdbc.OracleDriver</property>
            <property name="connection.url">jdbc:oracle:thin:@localhost:1521:orcl</property>
            <property name="connection.username">zhangzong</property>
            <property name="connection.password">123</property>
    
            <!-- SQL dialect (SQL 方言)-->
            <property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
        
            <!-- Drop and re-create the database schema on startup -->
             <property name="hbm2ddl.auto">create</property> 
    
            <!-- Echo all executed SQL to stdout  在控制台打印后台的SQL语句-->
            <property name="show_sql">true</property>
            
            <!-- 格式化显示SQL -->
            <property name="format_sql">true</property>    
            
            <!-- JDBC connection pool (use the built-in) -->
            <!-- <property name="connection.pool_size">1</property> -->
            
            <!-- Enable Hibernate's automatic session context management 指定当前session范围和上下文-->
            <!--  <property name="current_session_context_class">thread</property> -->
            
            <!-- Disable the second-level cache -->
            <!-- <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>-->
    
            <mapping resource="cn/zhang/entity/Dept.hbm.xml" />
            <mapping resource="cn/zhang/entity/Emp.hbm.xml" />
            
    
        </session-factory>
    
    </hibernate-configuration>

    06.用于获得session对象和关闭session对象的工具类HibernateUtil 

    package cn.zhang.util;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.cfg.Configuration;
    
    public class HibernateUtil {
        //初始化一个ThreadLocal对象,有get和set方法
        private static final ThreadLocal<Session> sessionTL=new ThreadLocal<Session>();
        
        private static Configuration configuration;
        
        private final static SessionFactory sessionFactory;
        static{
            
            configuration=new Configuration().configure();
            sessionFactory=configuration.buildSessionFactory();
        }
        //获得session对象
        public static Session currentSession() {
            //sessionTL的get方法根据当前线程返回其对应的线程内部变量,即Session对象,多线程情况下共享数据库连接是不安全的。
            //ThreadLocal保证了每个线程都有自己的session对象
            Session session=(Session)sessionTL.get();
            if (session==null) {
                session=sessionFactory.openSession();
                sessionTL.set(session);
            }
            
            return session;
        }
        //关闭session对象
        public static void closeSession() {
            Session session=(Session)sessionTL.get();
            sessionTL.set(null);
            session.close();
        }
    
    }

    07.测试类

    @Test //多对一的单向关联关系
        public void TestOne(){
            
            Session session = HibernateUtil.currentSession();
            
            Transaction tx = session.beginTransaction();
            Dept dept=new Dept();
            dept.setDeptname("开发部");
            
            Emp emp=new Emp();
            emp.setDept(dept);
            emp.setEmpname("张总");
            
            session.save(dept);
            session.save(emp);
            
            tx.commit();
            
            HibernateUtil.closeSession();        
        }

    二:配置双向的一对多关联

    在上一个例子中,已经建立Emp类到Dept类的多对一关联,下面再增加Dept到Emp类的一对多关联,

    在Dept类中增加一个集合类型的emps属性:

        private Set<Emp> emps=new HashSet<Emp>();//员工集合
        
        public Set<Emp> getEmps() {
            return emps;
        }
    
        public void setEmps(Set<Emp> emps) {
            this.emps = emps;
        }

    在Dept.hbm.xml中也会改变为:

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="cn.zhang.entity">
    <class name="Dept" table="DEPT">
    <id name="deptid" column="DEPTID">
       <generator class="sequence">
       <param name="sequence">SQ_Num</param>
       </generator>
    </id>
    <property name="deptname" type="string" column="deptname"/>
    <!-- 映射集合类型的emps属性 -->
    <!-- name属性:设定持久化类的属性名。此处为Dept类的emps -->
    <set name="emps" cascade="save-update" inverse="true">
    <!-- column属性设定与所关联的持久化类对应的表的外键,此处为EMP表的deptid字段 -->
    <key column="deptid"></key>
    <!-- class属性设定与所关联的持久化类,此处为Emp类 -->
    <one-to-many class="Emp"></one-to-many>
    </set>
    </class>
    </hibernate-mapping>

    补充:cascade属性和inverse属性(会新写一篇博客)

     01."cascade"属性

       "cascade"-直译过来就是"级联、串联"的意思,书面化的解释为"该属性会使我们在操作主对象时,同时Hibernate帮助我们完成从属对象 相应的操作(比如,有Customer和Order这两张表,关系为一对多,只使用JDBC删除Customer表中的一行记录时,我们还需要手动的将 Order表中与之关联的记录全都删除,使用Hibernate的'cascade'属性后,当我们删除一条Customer记录时,Hibernate 会帮助我们完成相应Order表记录的删除工作,方便了我们的工作)"。

     02."inverse"属性

           "inverse" -直译过来就是"反转,使颠倒"的意思,书面化的解释为"是否将关系维护的权力交给对方"(这个解释真够蛋疼的-_-!!,就是理解不了)。 Hibernate中的"inverse"属性只有两个值"true"和"false"。"true"表示将关系维护的权力交给对方,"false"表示不交出维护权力(默认值)。

    推荐博客:http://www.cnblogs.com/o-andy-o/archive/2012/03/26/2418235.html

    测试:

        @Test  
        public void TestThree(){
            //获得session对象
            Session session = HibernateUtil.currentSession();
            //开启事务
            Transaction tx = session.beginTransaction();
            //建立一个Dept对象和Emp对象
    
            Dept dept=new Dept();
            dept.setDeptname("就业部");
            
            Emp emp=new Emp();
            emp.setEmpname("坤坤");
            //建立Dept和Emp对象的一对多双向关联关系
            emp.setDept(dept);    
            dept.getEmps().add(emp);
            //保存Dept对象
            session.save(dept);
            
            //提交事务
            tx.commit();
            //关闭session连接
            HibernateUtil.closeSession();
    
        }

    三:配置单向多对多关联  --利用第三张表建立两张表之间的联系

    建立从Project(项目)类到Emp(员工)类的单向多对多关联。

    需在Project定义集合类型emps属性,Emp类中不需要定义集合类型的projects属性。

    Project.java

    package cn.zhang.entity;
    
    import java.util.HashSet;
    import java.util.Set;
    public class Project {
        private Integer proid;
        private String proname;
        private Set<Emp> emps = new HashSet<Emp>();
        public Integer getProid() {
            return proid;
        }
        public void setProid(Integer proid) {
            this.proid = proid;
        }
        public String getProname() {
            return proname;
        }
        public void setProname(String proname) {
            this.proname = proname;
        }
        public Set<Emp> getEmps() {
            return emps;
        }
        public void setEmps(Set<Emp> emps) {
            this.emps = emps;
        }        
    
    }

    Project.hbm.xml     --利用第三张表建立两张表之间的联系

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="cn.zhang.entity">
        <class name="Project" table="PROJECT">
            <id name="proid" type="java.lang.Integer">
                <generator class="sequence">
              <param name="sequence">SQ_Num</param>
               </generator>
            </id>
            <property name="proname" type="java.lang.String" column="PRONAME"/>
            <!-- 多对多关联 -->
            <set name="emps" table="PROEMP" cascade="save-update"  >
                <key column="proid" />
                <many-to-many class="Emp" column="empno" />             
            </set>      
        </class>
    </hibernate-mapping>

    测试:

        @Test
        public void TestOne(){
            Session session = HibernateUtil.currentSession();
            Transaction tx = session.beginTransaction();
            //创建EMP对象
            Emp emp=new Emp();
            emp.setEmpname("李小龙");
            
            //创建Pro对象
            Project pro=new Project();
            pro.setProname("海淀花园");
        
            //指定工程需要的员工
            pro.getEmps().add(emp);
                        
            session.save(pro);
            
            // 事务提交
            tx.commit();
                
            HibernateUtil.closeSession();
        }
         

    三:配置双向多对多关联    --利用第三张表建立两张表之间的联系

    对于双向多对多关联,需要把一端的inverse属性设为true,关联的两端都可以使用<set>元素。

    Project类--定义集合类型的emps属性

    Emp类--定义集合类型的projects属性

    Project.java:

    package cn.zhang.entity;
    
    import java.util.HashSet;
    import java.util.Set;
    
    public class Project {
        private Integer proid;
        private String proname;
        private Set<Emp> emps = new HashSet<Emp>();
        public Integer getProid() {
            return proid;
        }
        public void setProid(Integer proid) {
            this.proid = proid;
        }
        public String getProname() {
            return proname;
        }
        public void setProname(String proname) {
            this.proname = proname;
        }
        public Set<Emp> getEmps() {
            return emps;
        }
        public void setEmps(Set<Emp> emps) {
            this.emps = emps;
        }
        
        
    
    }

    Emp.java:

    package cn.zhang.entity;
    
    import java.util.HashSet;
    import java.util.Set;
    
    //员工实体类
    public class Emp {
        
        private Integer empno;
        
        private String empname;
        
        private Set<Project> projects = new HashSet<Project>();
        
        public Set<Project> getProjects() {
            return projects;
        }
    
        public void setProjects(Set<Project> projects) {
            this.projects = projects;
        }
    
        public Integer getEmpno() {
            return empno;
        }
    
        public void setEmpno(Integer empno) {
            this.empno = empno;
        }
    
        public String getEmpname() {
            return empname;
        }
    
        public void setEmpname(String empname) {
            this.empname = empname;
        }
            
    }

    Project.hbm.xml

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="cn.zhang.entity">
        <class name="Project" table="PROJECT">
            <id name="proid" type="java.lang.Integer">
                <generator class="sequence">
              <param name="sequence">SQ_Num</param>
               </generator>
            </id>
            <property name="proname" type="java.lang.String" column="PRONAME"/>
            <!-- 多对多关联 -->
            <set name="emps" table="PROEMP" cascade="save-update"  >
                <key column="proid" />
                <many-to-many class="Emp" column="empno" />             
            </set>      
        </class>
    </hibernate-mapping>

    Emp.hbm.xml

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="cn.zhang.entity">
        <class name="Emp" table="EMP">
            <id name="empno" column="empno">
                <generator class="sequence">
                    <param name="sequence">SQ_Num</param>
                </generator>
            </id>
            <property name="empname" type="string" column="empname" />
    
            <!--多对多关联 -->
            <set name="projects" table="PROEMP" cascade="save-update" inverse="true">
                <key column="empno" />
                <many-to-many class="Project" column="proid" />
            </set>
        </class>
    </hibernate-mapping>

    测试:

    @Test
        public void TestOne(){
            Session session = HibernateUtil.currentSession();
            Transaction tx = session.beginTransaction();
            //创建EMP对象
            Emp emp=new Emp();
            emp.setEmpname("李小龙");
            Emp emp2=new Emp();
            emp2.setEmpname("小龙");
            Emp emp3=new Emp();
            emp3.setEmpname("李龙");
            //创建Pro对象
            Project pro=new Project();
            pro.setProname("海淀花园");
            Project pro2=new Project();
            pro2.setProname("海淀花园fd");
            //指定工程需要的员工
            pro.getEmps().add(emp);
            pro.getEmps().add(emp2);
            pro.getEmps().add(emp3);
            
            pro2.getEmps().add(emp3);
            pro2.getEmps().add(emp2);
            //指定员工所属的工程
            //emp.getProjects().add(pro);
            
            session.save(pro);
            session.save(pro2);
            
            // 事务提交
            tx.commit();
                
            HibernateUtil.closeSession();
        }

    注意:双向多对多,还可以拆成两个多对一

    四:建立多对多双向关联 拆成两个一对多  --利用第三张表建立两张表之间的联系

    主要思想:新建立一个关系实体类和两张表关联的映射文件,主要在此映射文件中配置关联关系,其他两个映射文件只要配置基础映射

    ProEmp.java

    package cn.zhang.entity;
    //关联实体类
    public class ProEmp {
        private Integer id;
        private Project pro; //项目集合
        private Emp emp; //部门集合
        public Integer getId() {
            return id;
        }
        public void setId(Integer id) {
            this.id = id;
        }
        public Project getPro() {
            return pro;
        }
        public void setPro(Project pro) {
            this.pro = pro;
        }
        public Emp getEmp() {
            return emp;
        }
        public void setEmp(Emp emp) {
            this.emp = emp;
        }
    
    }

    Emp.java

    package cn.zhang.entity;
    
    import java.util.HashSet;
    import java.util.Set;
    
    //员工实体类
    public class Emp {
        
        private Integer empno;
        
        private String empname;
        
        private Set<ProEmp> projects = new HashSet<ProEmp>();//与ProEmp关联
        
        public Set<ProEmp> getProjects() {
            return projects;
        }
    
        public void setProjects(Set<ProEmp> projects) {
            this.projects = projects;
        }
    
        public Integer getEmpno() {
            return empno;
        }
    
        public void setEmpno(Integer empno) {
            this.empno = empno;
        }
    
        public String getEmpname() {
            return empname;
        }
    
        public void setEmpname(String empname) {
            this.empname = empname;
        }
        
        
    
    }

    Project.java

    package cn.zhang.entity;
    
    import java.util.HashSet;
    import java.util.Set;
    
    //员工实体类
    public class Emp {
        
        private Integer empno;
        
        private String empname;
        
        private Set<ProEmp> projects = new HashSet<ProEmp>();//与ProEmp关联
        
        public Set<ProEmp> getProjects() {
            return projects;
        }
    
        public void setProjects(Set<ProEmp> projects) {
            this.projects = projects;
        }
    
        public Integer getEmpno() {
            return empno;
        }
    
        public void setEmpno(Integer empno) {
            this.empno = empno;
        }
    
        public String getEmpname() {
            return empname;
        }
    
        public void setEmpname(String empname) {
            this.empname = empname;
        }
        
    }

    Emp.hbm.xml  

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="cn.zhang.entity">
        <class name="Emp" table="EMP">
            <id name="empno" column="empno">
                <generator class="sequence">
                    <param name="sequence">SQ_Num</param>
                </generator>
            </id>
            <property name="empname" type="string" column="empname" />
        </class>
    </hibernate-mapping>

    Project.hbm.xml

    <?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
    <hibernate-mapping package="cn.zhang.entity">
        <class name="Project" table="PROJECT">
            <id name="proid" type="java.lang.Integer">
                <generator class="sequence">
              <param name="sequence">SQ_Num</param>
               </generator>
            </id>
            <property name="proname" type="java.lang.String" column="PRONAME"/>    
        </class>
    </hibernate-mapping>

    最后别忘了在大配置中配置引用映射文件哦!

    测试:

    @Test
        public void TestOne(){
            Session session = HibernateUtil.currentSession();
            Transaction tx = session.beginTransaction();
            //创建EMP对象
            Emp emp=new Emp();
            emp.setEmpname("李小龙");
            
            //创建Pro对象
            Project pro=new Project();
            pro.setProname("海淀花园");
            
            ProEmp pEmp=new ProEmp();    
            
               //指定工程需要的员工
               pEmp.setEmp(emp);
               //指定员工所属的工程
            pEmp.setPro(pro);
            
            session.save(pro);
            session.save(emp);
            session.save(pEmp);
            
            
            // 事务提交
            tx.commit();
                
            HibernateUtil.closeSession();
        }

     

  • 相关阅读:
    初识 Rabbitmq
    Lambda表达式(C语言-gcc编译器)
    二叉树转换成双向链表
    进程的内存分布
    Linux shell之数组
    Ubuntu 使用Gparted工具扩大第一分区方法步骤
    Android源码编译出错解决办法
    IIC总线解析
    VirtualBox Ubuntu虚拟机串口编程
    ubuntu虚拟机上解决克隆github代码慢的方法
  • 原文地址:https://www.cnblogs.com/zhangzongle/p/5766912.html
Copyright © 2020-2023  润新知