zoukankan      html  css  js  c++  java
  • Hibernate第四篇【集合映射、一对多和多对一】

    前言

    前面的我们使用的是一个表的操作,但我们实际的开发中不可能只使用一个表的…因此,本博文主要讲解关联映射

    集合映射

    需求分析:当用户购买商品,用户可能有多个地址。

    数据库表

    我们一般如下图一样设计数据库表,一般我们不会在User表设计多个列来保存地址的。因为每个用户的地址个数都不一的,会造成数据冗余

    • 创建两张数据表,一张保存着用户的信息,一张保存着地址的信息。地址表使用外键来引用用户表

    这里写图片描述

    实体

    由于地址只是使用String类型来保存着,那么我们直接使用一个User对象就可以了

    
    public class User {
    
        private String id;
        private String username;
        private String password;
        private Set<String> address;
    
        //各种setter和getter

    映射文件

    
    <?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">
    
    <!--在domain包下-->
    <hibernate-mapping package="zhongfucheng.domain">
    
        <class name="User" table="user">
    
            <!--主键映射-->
            <id name="id" column="id" >
                <generator class="native"/>
            </id>
    
            <!--普通字段映射-->
            <property name="username" column="username"></property>
            <property name="password" column="password"></property>
    
            <!--
                 Set:
                    name: 映射集合的名称
                    table:集合的属性要映射到哪张表(address)
                 key:
                    column:指定要映射的表(address)中的外键列
                    element:要映射的表的其他字段
                        类型一定要指定!
            -->
            <set name="address" table="address">
                <key column="user_id"></key>
                <element column="addr" type="string"></element>
            </set>
    
    
        </class>
    </hibernate-mapping>
    

    测试

    
    package zhongfucheng.domain;
    
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.classic.Session;
    
    /**
     * Created by ozc on 2017/5/6.
     */
    public class App {
        public static void main(String[] args) {
    
            //创建对象
    
            User user = new User();
            user.setUsername("123");
            user.setPassword("1234");
            user.getAddress().add("广州");
    
    
            //获取加载配置管理类
            Configuration configuration = new Configuration();
    
            //加载User的映射文件!
            configuration.configure().addClass(User.class);
    
            //创建Session工厂对象
            SessionFactory factory = configuration.buildSessionFactory();
    
            //得到Session对象
            Session session = factory.openSession();
    
            //使用Hibernate操作数据库,都要开启事务,得到事务对象
            Transaction transaction = session.getTransaction();
    
            //开启事务
            transaction.begin();
    
            session.save(user);
            //提交事务
            transaction.commit();
    
            //关闭Session
            session.close();
        }
    }
    

    这里写图片描述


    List集合映射配置

    既然我们现在已经会了如何配置Set集合了,List集合又怎么配置呢??

    想一下,List集合和Set集合有什么区别…List集合是有序的,因此要多配置一个列来维护数据的有序性!

            <list name="address" table="address">
                <key column="user_id"></key>
    
                <!--index是关键字,不能使用!!!!-->
                <list-index column="index"></list-index>
                <element column="addr" type="string"></element>
            </list>

    Map集合映射配置

    Map集合和Collection集合的区别就是键值对模型,那么在配置的时候多一个key即可!

    
            <map name="address" table="address">
                <key column="user_id"  ></key>
                <map-key type="string" column="short"></map-key>
                <element type="string" column="addr"></element>
            </map>

    这里写图片描述


    一对多和多对一

    上面我们讲解了集合映射是怎么配置的,那集合装载的元素有没有可能是对象呢??而不是简单的String类型..那个就太多了!一般地,我们集合装载的都是对象,而不是简单的String,如果我们的装载在集合的数据有很多类型,那么String就不能用了!…

    需求:部门与员工之间的关系

    • 一个部门有多个员工; 【一对多】
    • 多个员工,属于一个部门 【多对一】

    设计数据库表

    员工表应该使用一个外键来记住部门表。这样才可以维护员工和部门之间的关系

    这里写图片描述

    设计实体

    部门实体要使用一个集合来记住所有的员工,员工要使用一个对象引用着部门

    这里写图片描述

    • Dept.java
    package zhongfucheng.domain;
    
    import java.util.HashSet;
    import java.util.Set;
    
    /**
     * Created by ozc on 2017/5/6.
     */
    public class Dept {
        private int id ;
    
        private Set<Employee> set = new HashSet<>();
    
        private String deptName;
    
        public String getDeptName() {
            return deptName;
        }
    
        public void setDeptName(String deptName) {
            this.deptName = deptName;
        }
    
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public Set<Employee> getSet() {
            return set;
        }
    
        public void setSet(Set<Employee> set) {
            this.set = set;
        }
    }
    
    
    • Employee.java
    
    package zhongfucheng.domain;
    
    /**
     * Created by ozc on 2017/5/6.
     */
    public class Employee {
    
    
        private int id;
        private String empName;
        private double salary;
        private Dept dept;
    
        public Dept getDept() {
            return dept;
        }
    
        public void setDept(Dept dept) {
            this.dept = dept;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getEmpName() {
            return empName;
        }
    
        public void setEmpName(String empName) {
            this.empName = empName;
        }
    
        public double getSalary() {
            return salary;
        }
    
        public void setSalary(double salary) {
            this.salary = salary;
        }
    }
    

    映射分析

    我们在写映射配置文件之前,分析一下怎么写。以部门映射配置文件为例

    现在使用了一个Set集合来维护与员工的关系,Set集合的类型是员工对象…因此在映射文件中需要以下几点

    • 映射集合属性的名称(employees)
    • 映射集合对应的数据表(employee)
    • 对应的数据表的外键字段(dept_id)
    • 集合中的元素类型(Employee)【通过这个类型,Hibernate就可以找到对应类型的映射文件,从而得到对应的信息!】

    这里写图片描述

    部门映射配置文件

    
    <?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">
    
    <!--在domain包下-->
    <hibernate-mapping package="zhongfucheng.domain">
    
        <class name="Dept" table="dept">
            <id column="id" name="id">
                <generator class="native">
    
                </generator>
            </id>
    
            <!--普通字段映射-->
            <property name="deptName" column="deptname"></property>
    
            <!--维护关系的是Set集合,对应employee表-->
            <set  cascade="save-update" name="set" table="employee">
    
                <!--employee的外键列是dept_no-->
                <key column="dept_no"></key>
    
                <!--一个部门对应多个员工,集合的类型是Employee-->
                <one-to-many class="Employee" ></one-to-many>
            </set>
        </class>
    
    </hibernate-mapping>
    

    员工映射配置文件

    
    <?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">
    
    <!--在domain包下-->
    <hibernate-mapping package="zhongfucheng.domain">
    
        <class name="Employee" table="employee">
            <id column="id" name="id">
                <generator class="native">
    
                </generator>
            </id>
    
            <!--普通字段数据-->
            <property name="empName" column="empName"></property>
            <property name="salary" column="salary"></property>
    
            <!--Hibernate这个标签可看成在当前表中设置一个外键dept_no-->
            <many-to-one name="dept" class="Dept" column="dept_no"></many-to-one>
        </class>
    
    </hibernate-mapping>
    

    在“一”的一方测试

    
    package zhongfucheng.domain;
    
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.classic.Session;
    
    /**
     * Created by ozc on 2017/5/6.
     */
    public class App {
        public static void main(String[] args) {
    
            //创建对象
            Dept dept = new Dept();
            dept.setDeptName("开发部");
    
            Employee zs = new Employee();
            zs.setEmpName("张珊");
            zs.setSalary(1111);
            Employee ls = new Employee();
            ls.setEmpName("李四");
            ls.setSalary(2222);
    
            //添加关系
            dept.getSet().add(zs);
            dept.getSet().add(ls);
    
            //获取加载配置管理类
            Configuration configuration = new Configuration();
    
            //加载User的映射文件!
            configuration.configure().addClass(Dept.class).addClass(Employee.class);
    
            //创建Session工厂对象
            SessionFactory factory = configuration.buildSessionFactory();
    
            //得到Session对象
            Session session = factory.openSession();
    
            //使用Hibernate操作数据库,都要开启事务,得到事务对象
            Transaction transaction = session.getTransaction();
    
            //开启事务
            transaction.begin();
    
    
            session.save(dept);
            session.save(zs);
            session.save(ls);
    
            //提交事务
            transaction.commit();
    
            //关闭Session
            session.close();
        }
    }
    

    Hibernate执行了5条SQL语句

    这里写图片描述


    在“多”的一方测试

    
    package zhongfucheng.domain;
    
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.hibernate.classic.Session;
    
    /**
     * Created by ozc on 2017/5/6.
     */
    public class App {
        public static void main(String[] args) {
    
            //创建对象
            Dept dept = new Dept();
            dept.setDeptName("开发部");
    
            Employee zs = new Employee();
            zs.setEmpName("张珊");
            zs.setSalary(1111);
            Employee ls = new Employee();
            ls.setEmpName("李四");
            ls.setSalary(2222);
    
            //维护关系
            zs.setDept(dept);
            ls.setDept(dept);
    
    
    
            //获取加载配置管理类
            Configuration configuration = new Configuration();
    
            //加载User的映射文件!
            configuration.configure().addClass(Dept.class).addClass(Employee.class);
    
            //创建Session工厂对象
            SessionFactory factory = configuration.buildSessionFactory();
    
            //得到Session对象
            Session session = factory.openSession();
    
            //使用Hibernate操作数据库,都要开启事务,得到事务对象
            Transaction transaction = session.getTransaction();
    
            //开启事务
            transaction.begin();
    
    
            session.save(dept);
            session.save(zs);
            session.save(ls);
    
    
    
            //提交事务
            transaction.commit();
    
            //关闭Session
            session.close();
        }
    }
    

    Hibernate执行了3条SQL

    这里写图片描述

    一对多和多对一总结

    在一对多与多对一的关联关系中,保存数据最好的通过多的一方来维护关系,这样可以减少update语句的生成,从而提高hibernate的执行效率!

    • 配置一对多与多对一, 这种叫“双向关联”
    • 只配置一对多, 叫“单项一对多”
    • 只配置多对一, 叫“单项多对一”

    值得注意是:配置了哪一方,哪一方才有维护关联关系的权限!

    • 当我在部门中不配置员工的关联关系了,那么在操作部门的时候就不能得到员工的数据了【也就是:在保存部门时,不能同时保存员工的数据】

  • 相关阅读:
    1046 Shortest Distance (20 分)(模拟)
    1004. Counting Leaves (30)PAT甲级真题(bfs,dfs,树的遍历,层序遍历)
    1041 Be Unique (20 分)(hash散列)
    1036 Boys vs Girls (25 分)(查找元素)
    1035 Password (20 分)(字符串处理)
    1044 Shopping in Mars (25 分)(二分查找)
    onenote使用小Tip总结^_^(不断更新中...)
    1048 Find Coins (25 分)(hash)
    三个故事
    领导者的举止
  • 原文地址:https://www.cnblogs.com/zhong-fucheng/p/7202967.html
Copyright © 2011-2022 走看看