zoukankan      html  css  js  c++  java
  • Hibernate_day03--课程安排_表之间关系_一对多操作

    Hibernate_day03

    上节内容

    今天内容

    表与表之间关系回顾(重点)

    Hibernate的一对多操作(重点)

    一对多映射配置(重点)

    一对多级联操作

    一对多级联保存

    一对多级联删除

    一对多修改操作(inverse属性)

    Hibernate多对多操作

    多对多映射配置

    多对多级联保存

    多对多级联删除(了解)

    维护第三张表关系

    Hibernate_day03

    上节内容

    1 实体类编写规则

    2 hibernate主键生成策略

    3 实体类操作

    (1)crud操作

    (2)实体类对象状态

    4 hibernate的一级缓存

    5 hibernate的事务操作

    (1)事务代码规则写法

    6 hibernate其他的api(查询)

    今天内容

    1 表与表之间关系回顾

    1)一对多(客户和联系人)

    2)多对多(用户和角色)

    2 hibernate一对多操作

    1*一对多映射配置

    2)一对多级联保存(同时操作多个表进行保存)

    3)一对多级联删除

    (4)inverse属性

    3 hibernate多对多操作

    1*多对多映射配置

    2)多对多级联保存(重点)

    (3)多对多级联删除

    4)维护第三张表

    表与表之间关系回顾(重点)

    1 一对多

    (1)分类和商品关系,一个分类里面有多个商品,一个商品只能属于一个分类

    (2)客户和联系人是一对多关系

    - 客户:与公司有业务往来,百度、新浪、360

    - 联系人:公司里面的员工,百度里面有很多员工,联系员工

    ** 公司和公司员工的关系

    - 客户是一,联系人是多

    - 一个客户里面有多个联系人,一个联系人只能属于一个客户

    (3)一对多建表:通过外键建立关系

    2 多对多

    (1)订单和商品关系,一个订单里面有多个商品,一个商品属于多个订单

    (2)用户和角色多对多关系

    - 用户: 小王、小马、小宋

    - 角色:总经理、秘书、司机、保安

    ** 比如小王 可以 是总经理,可以是司机

    ** 比如小宋 可以是司机,可以是秘书,可以保安

    ** 比如小马 可以是 秘书,可以是总经理

    一个用户里面可以有多个角色,一个角色里面可以有多个用户

    (3)多对多建表:创建第三张表维护关系

    3 一对一

    (1)在中国,一个男人只能有一个妻子,一个女人只能有一个丈夫

    Hibernate的一对多操作(重点)

    一对多映射配置(重点)

    以客户和联系人为例:客户是一,联系人是多

    第一步 创建两个实体类,客户和联系人

    第二步 让两个实体类之间互相表示

    (1)在客户实体类里面表示多个联系人

    - 一个客户里面有多个联系人

     

        //在客户实体类里面表示多个联系人,一个客户有多个联系人
        //hibernate要求使用集合表示多的数据,使用set集合
        private Set<LinkMan> setLinkMan = new HashSet<LinkMan>();
    
        public Set<LinkMan> getSetLinkMan() {
            return setLinkMan;
        }
        public void setSetLinkMan(Set<LinkMan> setLinkMan) {
            this.setLinkMan = setLinkMan;
        }

    具体:

    public class Customer {
        private Integer cid;// 客户id
        private String custName;// 客户名称
        private String custLevel;// 客户级别
        private String custSource;// 客户来源
        private String custPhone;// 联系电话
        private String custMobile;// 手机
        // 在客户实体类里面表示多个联系人,一个客户有多个联系人
        // hibernate要求使用集合表示多的数据,使用set集合
        private Set<LinkMan> setLinkMan = new HashSet<LinkMan>();
        public Set<LinkMan> getSetLinkMan() {
            return setLinkMan;
        }
        public void setSetLinkMan(Set<LinkMan> setLinkMan) {
            this.setLinkMan = setLinkMan;
        }
        public Integer getCid() {
            return cid;
        }
        public void setCid(Integer cid) {
            this.cid = cid;
        }
        public String getCustName() {
            return custName;
        }
        public void setCustName(String custName) {
            this.custName = custName;
        }
        public String getCustLevel() {
            return custLevel;
        }
        public void setCustLevel(String custLevel) {
            this.custLevel = custLevel;
        }
        public String getCustSource() {
            return custSource;
        }
        public void setCustSource(String custSource) {
            this.custSource = custSource;
        }
        public String getCustPhone() {
            return custPhone;
        }
        public void setCustPhone(String custPhone) {
            this.custPhone = custPhone;
        }
        public String getCustMobile() {
            return custMobile;
        }
        public void setCustMobile(String custMobile) {
            this.custMobile = custMobile;
        }
    }

    (2)在联系人实体类里面表示所属客户

    - 一个联系人只能属于一个客户

        //在联系人实体类里面表示所属客户,一个联系人只能属于一个客户
        private Customer customer;
        
        public Customer getCustomer() {
            return customer;
        }
        public void setCustomer(Customer customer) {
            this.customer = customer;
        }

    具体:

    public class LinkMan {
        private Integer lkm_id; // 联系人编号(主键)
        private String lkm_name;// 联系人姓名
        private String lkm_gender;// 联系人性别
        private String lkm_phone;// 联系人办公电话
        // 在联系人实体类里面表示所属客户,一个联系人只能属于一个客户
        private Customer customer;
        public Customer getCustomer() {
            return customer;
        }
        public void setCustomer(Customer customer) {
            this.customer = customer;
        }
        public Integer getLkm_id() {
            return lkm_id;
        }
        public void setLkm_id(Integer lkm_id) {
            this.lkm_id = lkm_id;
        }
        public String getLkm_name() {
            return lkm_name;
        }
        public void setLkm_name(String lkm_name) {
            this.lkm_name = lkm_name;
        }
        public String getLkm_gender() {
            return lkm_gender;
        }
        public void setLkm_gender(String lkm_gender) {
            this.lkm_gender = lkm_gender;
        }
        public String getLkm_phone() {
            return lkm_phone;
        }
        public void setLkm_phone(String lkm_phone) {
            this.lkm_phone = lkm_phone;
        }
    }


    第三步 配置映射关系

    (1)一般一个实体类对应一个映射文件

    (2)把映射最基本配置完成

    Customer.hbm.xml

        <!-- 1 配置类和表对应 
            class标签
            name属性:实体类全路径
            table属性:数据库表名称
        -->
    <class name="cn.itcast.entity.Customer" table="t_customer">
            <id name="cid" column="cid">
                <generator class="native"></generator>
            </id>
            <property name="custName" column="custName"></property>
            <property name="custLevel" column="custLevel"></property>
            <property name="custSource" column="custSource"></property>
            <property name="custPhone" column="custPhone"></property>
            <property name="custMobile" column="custMobile"></property>    
        </class>

    LinkMan.hbm.xml

    <!-- 1 配置类和表对应 
            class标签
            name属性:实体类全路径
            table属性:数据库表名称
        -->
        <class name="cn.itcast.entity.LinkMan" table="t_linkman">
            <id name="lkm_id" column="lkm_id">
                <generator class="native"></generator>
            </id>
            <property name="lkm_name" column="lkm_name"></property>
            <property name="lkm_gender" column="lkm_gender"></property>
            <property name="lkm_phone" column="lkm_phone"></property>

    (3)在映射文件中,配置一对多关系

    - 在客户映射文件中,表示所有联系人

    Customer.hbm.xml

            <!-- 在客户映射文件中,表示所有联系人
                使用set标签表示所有联系人
             -->
            <set name="setLinkMan">
                <!-- 一对多建表,有外键
                    hibernate机制,双向维护外键,在一和多那一方都配置外键
                    column属性值,外键名称
                 -->
                <key column="clid"></key>
                <!-- 客户所有的联系人,class里面写联系人的实体类全路径 -->
                <one-to-many class="cn.itcast.entity.LinkMan" />
            </set>

    - 在联系人映射文件中,表示所属客户

    LinkMan.hbm.xml

            <!-- 表示联系人所属客户
                name属性:因为在联系人实体类使用customer对象表示,写customer名称
                class属性:customer全路径
                column属性:外键名称
             -->
    <many-to-one name="customer" class="cn.itcast.entity.Customer"column="clid"></many-to-one>

    第四步 创建核心配置文件,把映射文件引入到核心配置文件中

    测试:

    运行HibernateUtils.java工具类

    public class HibernateUtils {
        static Configuration cfg = null;
        static SessionFactory sessionFactory = null;
        //静态代码块实现
        static {
            //加载核心配置文件
            cfg = new Configuration().configure();
            sessionFactory = cfg.buildSessionFactory();
        }
        //提供返回与本地线程绑定的session方法
        public static Session getSessionObject() {
            return sessionFactory.getCurrentSession();
        }
        // 提供方法返回sessionFactory
        public static SessionFactory getSessionFactory() {
            return sessionFactory;
        }
        public static void main(String[] args) {
        }
    }

    一对多级联操作

    级联操作

    1 级联保存

    (1)添加一个客户,为这个客户添加多个联系人

    2 级联删除

    (1)删除某一个客户,这个客户里面的所有的联系人也删除

    一对多级联保存

    1 添加客户,为这个客户添加一个联系人

    (1)复杂写法:

    public class HibernateOnetoMany {
        //演示一对多级联保存 复杂写法
        @Test
        public void testAddDemo1() {
            SessionFactory sessionFactory = null;
            Session session = null;
            Transaction tx = null;
            try{
                sessionFactory = HibernateUtils.getSessionFactory();
                //与本地线程绑定的session
                session = sessionFactory.openSession();
                //开启事务
                tx = session.beginTransaction();
                //添加一个客户,为这个客户添加一个联系人
                //1.创建客户和联系人对象
                Customer customer = new Customer();
                customer.setCustName("小李");
                customer.setCustLevel("vip");
                customer.setCustSource("网络");
                customer.setCustPhone("999");
                customer.setCustMobile("666");
                LinkMan linkman = new LinkMan();
                linkman.setLkm_name("小容");
                linkman.setLkm_gender("女");
                linkman.setLkm_phone("520");
                //2 在客户表示所有联系人,在联系人表示客户        
                // 建立客户对象和联系人对象关系
                //2.1 把联系人对象 放到客户对象的set集合里面
                customer.getSetLinkMan().add(linkman);
                //2.2把客户对象放到联系人里面
                linkman.setCustomer(customer);
                //3 保存到数据库
                session.save(customer);
                session.save(linkman);
                //提交事务
                tx.commit();
            }catch(Exception e) {
                e.printStackTrace();
                //回滚事务
                tx.rollback();
            }finally {
                //关闭操作
                session.close();
                sessionFactory.close();
            }
        }
    }


    (2)简化写法

    - 一般根据客户添加联系人

    第一步 在客户映射文件中进行配置

    - 在客户映射文件里面set标签进行配置

    第二步 创建客户和联系人对象,只需要把联系人放到客户里面就可以了,最终只需要保存客户就可以了

    //演示一对多级联保存 简单写法
        @Test
        public void testAddDemo2() {
            SessionFactory sessionFactory = null;
            Session session = null;
            Transaction tx = null;
            try{
                sessionFactory = HibernateUtils.getSessionFactory();
                //与本地线程绑定的session
                session = sessionFactory.openSession();
                //开启事务
                tx = session.beginTransaction();
                //添加一个客户,为这个客户添加一个联系人
                //1.创建客户和联系人对象
                Customer customer = new Customer();
                customer.setCustName("百度");
                customer.setCustLevel("普通客户");
                customer.setCustSource("网络");
                customer.setCustPhone("999");
                customer.setCustMobile("777");
                LinkMan linkman = new LinkMan();
                linkman.setLkm_name("小宏");
                linkman.setLkm_gender("男");
                linkman.setLkm_phone("555");
                //2 把联系人对象 放到客户对象的set集合里面
                customer.getSetLinkMan().add(linkman);
                //3 保存客户
                session.save(customer);
                //提交事务
                tx.commit();
            }catch(Exception e) {
                e.printStackTrace();
                //回滚事务
                tx.rollback();
            }finally {
                //关闭操作
                session.close();
                sessionFactory.close();
            }
        }

    一对多级联删除

    1 删除某个客户,把客户里面所有的联系人删除

    2 具体实现

    第一步 在客户映射文件set标签,进行配置

    (1)使用属性cascade属性值 delete

    第二步 在代码中直接删除客户

    (1)根据id查询对象,调用session里面delete方法删除

    3 执行过程:

    (1)根据id查询客户

    (2)根据外键id值查询联系人

    (3)把联系人外键设置为null

    (4)删除联系人和客户

    一对多修改操作(inverse属性)

    1 让小容联系人所属客户不是小李,而是小王

                //1 根据id查询小容联系人,根据id查询小王的客户
                Customer customer  = session.get(Customer.class, 2);
                LinkMan linkman = session.get(LinkMan.class, 1);
                //2 设置持久态对象值
                //把联系人(小容)放到客户(小王)里面
                customer.getSetLinkMan().add(linkman);
                //把客户(小王)放到联系人(小容)里面
                linkMan.setCustomer(customer);

    2 inverse属性

    (1)因为hibernate双向维护外键,在客户和联系人里面都需要维护外键,修改客户时候修改一次外键,修改联系人时候也修改一次外键,造成效率问题

    (2)解决方式:让其中的一方不维护外键

    - 一对多里面,让其中一方放弃外键维护

    - 一个国家有总统,国家有很多人,总统不能认识国家所有人,国家所有人可以认识总统

    (3)具体实现:

    在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性

  • 相关阅读:
    使用 VisualVM 进行性能分析及调优
    数据库乱码,频繁中断
    mysql 查看数据库中所有表的记录数
    MySQL数据库设置远程访问权限方法小结
    详解使用DockerHub官方的mysql镜像生成容器
    Docker的安装和使用说明——Docker for Windows
    CentOS7安装Docker与使用篇
    正则提取字符串中的字符串
    java parse 带英文单词的日期字符串 转 date (转化新浪微博api返回的时间)
    mysql function 中使用游标
  • 原文地址:https://www.cnblogs.com/justdoitba/p/7856697.html
Copyright © 2011-2022 走看看