zoukankan      html  css  js  c++  java
  • 03_Hibernate关系映射

    关系映射?

     Hibernate的主要目的就是JAVA程序员可以随心所欲的使用对象编程思维来操作数据库。一些数据库表的关系我们应该可以通过hibernate实现,比如数据库中用到的主外键关系,还有一些与主外键关系的设置,比如主键的信息被删除,外键关联的信息也要删除等,所以hibernate同样应该实现这种映射关系。

    系统设计中的三种实体关系

     

    数据库实体表之间的关系映射

            一对多:客户(customers)和订单(orders)的关系

                    一般在多的一方添加外键

            一对一:公司(company)和公司地址(address)的关系

                    在任意一方添加对方的主键作为外键

           

            多对多:订单(orders)和商品(products)数据表

                    关系上升为第三张表,分别引入双方的主键作为外键

    Hibernate关联映射

    hibernate的一对多关联映射又分为两种实现方式:

           单项关联:立从employee到department的多对一关联,或者仅仅建立从department到employee的一对多关联。

           双项关联:既建立从employee到department的多对一关联,又建立从department到employee的一对多关联。

    1.单向多对一

    员工emp和部门dept,

    规则:在多的一方配置,多的一方要封装一个(一的一方)属性
    name:是一的一方的属性名 , column:外键 列名 class:one的类的全路径
    <many-to-one name="dept" column="deptid" class="com.manytoone.Dept" not-null="false" cascade="all">
    </many-to-one>

    Emp.java

    public class Emp {
        private Integer eid;
        private String ename;
        private Dept dept;
    
        public Integer getEid() {
            return eid;
        }
    
        public void setEid(Integer eid) {
            this.eid = eid;
        }
    
        public String getEname() {
            return ename;
        }
    
        public void setEname(String ename) {
            this.ename = ename;
        }
    
        public Dept getDept() {
            return dept;
        }
    
        public void setDept(Dept dept) {
            this.dept = dept;
        }
    }

    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>
    <class name="com.manytoone.Emp" table="emp">
        <id name="eid" column="eid" type="java.lang.Integer" length="10">
            <!--主键生成策略-->
            <generator class="increment">
            </generator>
        </id>
        <!--ename属性-->
        <property name="ename" column="ename" type="java.lang.String" length="50">
        </property>
        <!--name:属性名  column:外键  class: 与name属性的全路径  cascade:表示会影响所关联的的表-->
        <many-to-one name="dept" column="deptid" class="com.manytoone.Dept" not-null="false" cascade="save-update">
        </many-to-one>
    </class>
    </hibernate-mapping>

    Dept.java

    public class Dept {
        private Integer did;
        private String dname;
    
        public Integer getDid() {
            return did;
        }
    
        public void setDid(Integer did) {
            this.did = did;
        }
    
        public String getDname() {
            return dname;
        }
    
        public void setDname(String dname) {
            this.dname = dname;
        }
    }

    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>
    <class name="com.manytoone.Dept" table="dept">
        <id name="did" column="did" type="java.lang.Integer" length="10">
            <!--主键生成策略-->
            <generator class="increment">
            </generator>
        </id>
        <!--dname属性-->
        <property name="dname" column="dname" type="java.lang.String" length="50">
        </property>
    </class>
    </hibernate-mapping>

    2.单向一对多关联

    dept->emp(单向一对多)

    规则:在一的一方配置,要封装一个set集合.
    <!-- name属性:表示一的一方set集合的属性,  table: 多的一方的表名 -->
    <set name="emps" table="emp" cascade="all">
        <key>
                <!-- 外键  -->
            <column name="deptid"></column>
        </key>
        <!-- class: many方的全类名  -->
        <one-to-many class="Emp"/>
    </set>

    dept.java

    public class Dept {
        private Integer did;
        private String dname;
        private Set<Emp> emps = new HashSet<Emp>();
    
        public Integer getDid() {
            return did;
        }
    
        public void setDid(Integer did) {
            this.did = did;
        }
    
        public String getDname() {
            return dname;
        }
    
        public void setDname(String dname) {
            this.dname = dname;
        }
    
        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>
    <class name="com.onetomany.Dept" table="dept" lazy="true">
        <id name="did" column="did" type="java.lang.Integer" length="10">
            <!--主键生成策略-->
            <generator class="increment">
            </generator>
        </id>
        <!--dname属性-->
        <property name="dname" column="dname" type="java.lang.String" length="50">
        </property>
        <!--关联级别及时加载,查询时会把关联的也会查询出来-->
        <set name="emps" table="emp" cascade="all" lazy="true">
            <key>
                <column name="deptid"></column> <!--外键-->
            </key>
            <one-to-many class="com.onetomany.Emp"/><!--外键关联的类-->
        </set>
    </class>
    </hibernate-mapping>

    Emp.java

    
    public class Emp {
        private Integer eid;
        private String ename;
        private Integer deptid;
    
        public Integer getEid() {
            return eid;
        }
    
        public void setEid(Integer eid) {
            this.eid = eid;
        }
    
        public String getEname() {
            return ename;
        }
    
        public void setEname(String ename) {
            this.ename = ename;
        }
    
        public Integer getDeptid() {
            return deptid;
        }
    
        public void setDeptid(Integer deptid) {
            this.deptid = deptid;
        }
    }
    

    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>
    <class name="com.onetomany.Emp" table="emp">
        <id name="eid" column="eid" type="java.lang.Integer" length="10">
            <!--主键生成策略-->
            <generator class="increment">
            </generator>
        </id>
        <!--ename属性-->
        <property name="ename" column="ename" type="java.lang.String" length="50">
        </property>
        <property name="deptid" column="deptid" type="java.lang.Integer" length="10">
        </property>
    </class>
    </hibernate-mapping>

    3.双向一对多*

    dept->Emp

    规则:1.在多的一方配置,多的一方要封装一个(一的一方)属性
               2.在一的一方配置,要封装一个set集合.
    上述两个配置综合

    Dept.java

    public class Dept {
        private Integer did;
        private String dname;
        private Set<Emp> emps = new HashSet<Emp>();
    
        public Integer getDid() {
            return did;
        }
    
        public void setDid(Integer did) {
            this.did = did;
        }
    
        public String getDname() {
            return dname;
        }
    
        public void setDname(String dname) {
            this.dname = dname;
        }
    
        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>
        <class name="com.doubleonetomany.Dept" table="dept">
            <id name="did" column="did" type="java.lang.Integer" length="10">
                <!--主键生成策略-->
                <generator class="increment">
                </generator>
            </id>
            <!--dname属性-->
            <property name="dname" column="dname" type="java.lang.String" length="50">
            </property>
            <set name="emps" table="emp" cascade="all">
                <key>
                    <column name="deptid"></column> <!--外键-->
                </key>
                <one-to-many class="com.doubleonetomany.Emp"/><!--外键关联的类-->
    
            </set>
        </class>
    </hibernate-mapping>

    Emp.java

    public class Emp {
        private Integer eid;
        private String ename;
        private Dept dept;
    
        public Integer getEid() {
            return eid;
        }
    
        public void setEid(Integer eid) {
            this.eid = eid;
        }
    
        public String getEname() {
            return ename;
        }
    
        public void setEname(String ename) {
            this.ename = ename;
        }
    
        public Dept getDept() {
            return dept;
        }
    
        public void setDept(Dept dept) {
            this.dept = dept;
        }
    }

    Emp.hbn.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>
    <class name="com.icss.doubleonetomany.Emp" table="emp">
        <id name="eid" column="eid" type="java.lang.Integer" length="10">
            <!--主键生成策略-->
            <generator class="increment">
            </generator>
        </id>
        <!--ename属性-->
        <property name="ename" column="ename" type="java.lang.String" length="50">
        </property>
        <!--name:属性名  column:外键  class: 与name属性的全路径  cascade:表示会影响所关联的的表-->
        <many-to-one name="dept" column="deptid" class="com.icss.doubleonetomany.Dept" not-null="false">
        </many-to-one>
    </class>
    </hibernate-mapping>

    4.双向一对一

    employee->joinpart 员工和入党申请书

    规则:在实体类中分别要定义对方类型的属性 
    在有外键一方配置 :<many-to-one name="joinpart" column="joinpart_id" class="JoinPart" cascade="save-update"></many-to-one>
    在没有外键的一方配置 :<one-to-one name="emp" class="Employee" property-ref="joinpart"></one-to-one>
    注:property-ref:对方封装的相关类型的属性

    Employee.java

    package com.icss.doubleonetoone;
    
    import java.util.Date;
    
    /**
     * Created by jiatp on 2019/8/2.
     */
    public class Employee {
        private Integer eid;
        private String name;
        private Date birthday;
        private JoinPart joinPart;
    
        public JoinPart getJoinPart() {
            return joinPart;
        }
    
        public void setJoinPart(JoinPart joinPart) {
            this.joinPart = joinPart;
        }
    
        public Integer getEid() {
            return eid;
        }
    
        public void setEid(Integer eid) {
            this.eid = eid;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Date getBirthday() {
            return birthday;
        }
    
        public void setBirthday(Date birthday) {
            this.birthday = birthday;
        }
    }
    

    Employee.hbm.java

    <?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>
        <class name="com.doubleonetoone.Employee" table="employee">
            <id name="eid" column="eid" type="java.lang.Integer" length="10">
                <generator class="increment"/>
            </id>
            <property name="name" column="name" type="java.lang.String" length="50">
            </property>
            <property name="birthday" column="birthday" type="java.util.Date">
            </property>
            <many-to-one name="joinPart" column="joinPart_id" class="com.doubleonetoone.JoinPart" cascade="save-update"></many-to-one>
        </class>
    </hibernate-mapping>
    JoinPart.java
    public class JoinPart {
        private Integer jid;
        private Date joindate;
        private Employee emp;
    
        public Integer getJid() {
            return jid;
        }
    
        public void setJid(Integer jid) {
            this.jid = jid;
        }
    
        public Date getJoindate() {
            return joindate;
        }
    
        public void setJoindate(Date joindate) {
            this.joindate = joindate;
        }
    
        public Employee getEmp() {
            return emp;
        }
    
        public void setEmp(Employee emp) {
            this.emp = emp;
        }
    }
    JoinPart.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>
        <class name="com.icss.doubleonetoone.JoinPart" table="joinPart">
            <id name="jid" column="jid" type="java.lang.Integer" length="10">
                <generator class="increment"/>
            </id>
            <property name="joindate" column="joindate" type="java.util.Date">
            </property>
            <one-to-one name="emp" class="com.doubleonetoone.Employee" property-ref="joinPart"></one-to-one>
        </class>
    </hibernate-mapping>

    5.双向多对多

    User->Role  用户和角色

    规则:双向多对多
    处理中间表,在中间表中存放它们的外键 
    name:集合类型的属性名   table:中间表的表名     column: 中间与之对应的外键 
    class :  后面many方的类的全路径   column: 后面many类对应中间表的外键 
    <set name="users" table="sys_role_user">
        <key column="r_id"></key>
        <many-to-many class="User" column="u_id"></many-to-many>
    </set>

    User.java

    public class User {
        private Integer uid;
        private String name;
        private Set<Role> roles = new HashSet<Role>(); //双向多对多
    
        public Integer getUid() {
            return uid;
        }
    
        public void setUid(Integer uid) {
            this.uid = uid;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Set<Role> getRoles() {
            return roles;
        }
    
        public void setRoles(Set<Role> roles) {
            this.roles = roles;
        }
    }

    User.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>
        <class name="com.doublemanytomany.User" table="user">
            <id name="uid" column="uid" type="java.lang.Integer" length="10">
                <!--主键生成策略-->
                <generator class="increment">
                </generator>
            </id>
            <property name="name" column="name" length="50" type="java.lang.String">
            </property>
            <!--inverses属性;true关联维护时将控制权交给对方-->
            <set name="roles" table="sys_role_user" inverse="true">
                <key column="u_id">
                </key>
                <many-to-many class="com.doublemanytomany.Role" column="r_id">
                </many-to-many>
            </set>
           
        </class>
    </hibernate-mapping>

    Role.java

    public class Role {
        private Integer rid;
        private String name;
        private Set<User> users = new HashSet<User>();  //多对多
    
        public Integer getRid() {
            return rid;
        }
    
        public void setRid(Integer rid) {
            this.rid = rid;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Set<User> getUsers() {
            return users;
        }
    
        public void setUsers(Set<User> users) {
            this.users = users;
        }
    }

    Role.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>
        <class name="com.doublemanytomany.Role" table="role">
            <id name="rid" column="rid" type="java.lang.Integer" length="10">
                <!--主键生成策略-->
                <generator class="increment">
                </generator>
            </id>
            <property name="name" type="java.lang.String" column="name" length="50">
            </property>
            <set name="users" table="sys_role_user">
                <key column="r_id">
                </key>
                <many-to-many class="com.doublemanytomany.User" column="u_id">
                </many-to-many>
            </set>
    
        </class>
    </hibernate-mapping>

    注意:对于双向 n-n 关联, 须把其中一端的 inverse 设置为 true, 否则可能会造成主键冲突.

    测试

    /**
     * Description:测试双向多对多关联
     * User:jiatp
     * Date: 2019/8/3 18:14
     */
    public class doublemanytomanyTest {
        @Test
        public void test(){
            Session session = HibernateUtils.openSession();
            Transaction ts = session.beginTransaction();
            //创建用户
            User user1 = new User();
            user1.setName("jtp");
    
            // 创建角色
            Role role = new Role();
            role.setName("CEO");
    
            //关联关系
            user1.getRoles().add(role);
            role.getUsers().add(user1);
            session.save(user1);
            session.save(role);
    
    
            ts.commit();
            session.close();
    
        }
    }

    只举例双向对多的例子,其余的自行测试。

  • 相关阅读:
    【JS教程08】数组及操作方法
    【JS教程07】事件属性及匿名函数
    【JS教程06】操作元素
    【JS教程05】获取元素的方法
    【JS教程04】条件语句
    多线程环境下非安全Dictionary引起的“已添加了具有相同键的项”问题
    GPT分区基础知识及如何在GPT分区上安装WIN7
    Jenkins TFS配置
    windows查看端口占用命令
    VS2015企业版序列号
  • 原文地址:https://www.cnblogs.com/jatpeo/p/11767538.html
Copyright © 2011-2022 走看看