Hibernate中表与表之间关系的处理(一对多)

一.表与表之间关系回顾

1.一对多

  • 分类和商品的关系,一个分类里面有多个商品,一个商品只能属于一个分类
  • 客户和联系人是一对多关系
    • 客户:与公司有业务往来,百度,新浪,360
    • 联系人:公司里面的员工,百度里面有很多员工,联系员工
  • 公司和公司员工的关系
  • 客户是一,联系人是多
    • 一个客户里面有多个联系人,一个联系人只能属于一个客户
  • 一对多建表,通过外键建立关系

这里写图片描述

2.多对多

  • 订单和商品关系,一个订单里面有多个商品,一个商品属于多个订单
  • 用户和角色多对多关系
    • 用户:小王,小马,小宋
    • 角色:总经理,秘书,司机,保安
    • 比如小王 可以 是总经理,可以是司机
    • 比如小宋 可以 是司机,可以是秘书,可以是保安
    • 比如小马 可以 是秘书,可以是总经理
    • 一个用户里面可以由多个角色,一个角色里面可以有多个用户
  • 多对多建表,创建第三张表维护关系

这里写图片描述

3.一对一

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

二.Hibernate的一对多操作

1.一对多映射配置

  • 导入hibernate jar包
    • 以客户和联系人为例:客户是一,联系人是多
(1).创建两个实体类,客户和联系人

这里写图片描述

这里写图片描述

(2).让两个实体类之间互相表示
  • 在客户实体类里面表示多个联系人
    • 一个客户里面有多个联系人

这里写图片描述

  • 在联系人实体类里面表示所属客户
    • 一个联系人只能属于一个客户

这里写图片描述

(3).配置映射关系
  • 一般一个实体类对应一个映射文件
  • 把映射最基本配置完成

Customer.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
                <class name="cn.st.web.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>

                </class>
</hibernate-mapping>   

LinkMan.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

                     <class name="cn.st.web.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>
</hibernate-mapping>            
  • 在映射文件中,配置一对多关系

Customer.hbm.xml

  • 在客户映射文件中,表示所有联系人
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

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

LinkMan.hbm.xml

  • 在联系人映射文件中,表示所属客户
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
                <class name="cn.st.web.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>
                           <!-- 表示联系人所属客户
                           name属性:因为在联系人实体类使用Customer对象表示,写customer名称
                           class属性:customer全路径
                           column属性:外键名称
                            -->
                            <many-to-one name="customer" class="cn.st.web.entity.Customer" column="clid" ></many-to-one>
                </class>
</hibernate-mapping>       
(4).创建核心配置文件,把映射文件引入到核心配置文件
 <mapping resource="cn/st/web/entity/Customer.hbm.xml"/>
<mapping resource="cn/st/web/entity/LinkMan.hbm.xml"/>

2.测试

这里写图片描述

这里写图片描述

三.一对多级联操作

1.级联保存

(1).一对多级联保存复杂写法
public void testAdd() {

           Session session=null;

           Transaction tx=null;     

           try {

               session=hibernateUtils.getSessionobject();

               tx=session.beginTransaction();

               //添加一个客户,为这个客户添加一个联系人
                //1.创建客户和联系人对象
               Customer customer=new Customer();
               customer.setCustName("传智播客");
                customer.setCustLevel("vip");
                customer.setCustSource("网络");
                customer.setCustPhone("110");
                customer.setCustMobile("999");

                LinkMan linkMan=new LinkMan();
                linkMan.setLkm_name("lucy");
                linkMan.setLkm_gender("男");
                linkMan.setLkm_phone("911");

                //2 在客户表示所有联系人,在联系人表示客户
                //建立客户对象和联系人对象关系
                //2.1 把联系人对象 放到客户实体类对象的set集合里面
                customer.getSetLinkMan().add(linkMan);
                //2.2 把客户对象放到联系人里面
                linkMan.setCustomer(customer);
               //3.保存到数据库
                session.save(customer);
                session.save(linkMan);

               tx.commit();//3.提交事务

           }catch(Exception e){
                 e.printStackTrace();
                 tx.rollback();//回滚事务
           }finally {
               if(session!=null)
               session.close();

        }
      }

这里写图片描述

(2).简化写法
  • 一般根据客户添加联系人
  • 第一步 在客户映射文件中进行配置
    • 在客户映射文件里面set标签进行配置
      这里写图片描述
  • 第二步 创建客户和联系人对象,只需要把联系人放到客户里面就可以了,最终只需要保存一个客户就可以了
 public void testAdd2() {

           Session session=null;

           Transaction tx=null;     

           try {
               session=hibernateUtils.getSessionobject();

               tx=session.beginTransaction();

                //1.创建客户和联系人对象
                Customer customer=new Customer();
                customer.setCustName("百度");
                customer.setCustLevel("普通客户");
                customer.setCustSource("网络");
                customer.setCustPhone("110");
                customer.setCustMobile("999");

                LinkMan linkMan=new LinkMan();
                linkMan.setLkm_name("小航");
                linkMan.setLkm_gender("男");
                linkMan.setLkm_phone("911");

                //2.把联系人放到客户里面
                customer.getSetLinkMan().add(linkMan);
                //3.保存客户
                session.save(customer);

               tx.commit();//3.提交事务

           }catch(Exception e){
                 e.printStackTrace();
                 tx.rollback();//回滚事务
           }finally {
               if(session!=null)
               session.close();

        }
      }

这里写图片描述

2.级联删除

  • 删除某个客户,把客户里面所有的联系人删除
  • 具体实现

    • 第一步 在客户映射文件set标签,进行配置
    • (1).使用属性cascade属性值 delete
      这里写图片描述
  • 第二步 在代码中直接删除客户

    • (1).根据id查询对象,调用session里面delete方法删除
      这里写图片描述
  • 执行过程

    • (1).根据id查询客户
      这里写图片描述
    • (2).根据外键查联系人
      这里写图片描述
    • (3).把联系人外键设置为null
      这里写图片描述
    • (4).删除联系人和客户
      这里写图片描述
 public void testDelete() {

           Session session=null;

           Transaction tx=null;     

           try {
               session=hibernateUtils.getSessionobject();

               tx=session.beginTransaction();

               Customer customer=session.get(Customer.class,1);

               session.delete(customer);


               tx.commit();//3.提交事务

           }catch(Exception e){
                 e.printStackTrace();
                 tx.rollback();//回滚事务
           }finally {
               if(session!=null)
               session.close();

        }
      }

3.级联修改(inverse属性值)

  • 让lucy联系人所属联系人不是传智播客,而是百度

“`
public void testUpdate() {

       Session session=null;

       Transaction tx=null;     

       try {

           session=hibernateUtils.getSessionobject();

           tx=session.beginTransaction();

           //根据id查询lucy联系人,根据id查询百度的客户

           Customer baidu=session.get(Customer.class,3);

           LinkMan lucy=session.get(LinkMan.class,3);
           //2.设置持久态对象值
           //把联系人放到客户里面
           baidu.getSetLinkMan().add(lucy);
           //把客户放到联系人里面
           lucy.setCustomer(baidu);
           //持久态会自动更新数据库

           tx.commit();
       }catch(Exception e){
             e.printStackTrace();
             tx.rollback();//回滚事务
       }finally {
           if(session!=null)
           session.close();

    }
  }
  • inverse属性
    • (1).因为Hibernate是双向维护外键,在客户和联系人里面都需要维护外键,修改客户时候修改一次外键,修改联系人时候也修改一次外键,造成效率问题
      这里写图片描述
    • (2).解决方式:让其中的一方不维护外键
      • 一对多里面,让其中一方放弃外键维护
      • 一个国家有总统,国家有很多人,总统不能认识国家所有人,国家所有人可以认识总统
  • (3).具体实现
    • 在放弃关系维护映射文件中,进行配置,在set标签上使用inverse属性
      这里写图片描述
      之后就只修改一次了

这里写图片描述

END!!!!!

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值