Hibernate知识点复习之三

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate知识点复习之三相关的知识,希望对你有一定的参考价值。

HIbernate知识点复习之三

案例需求描述:

存在着一个客户对应多个联系人的情况,单独在联系人管理模块中对联系人信息进行维护,功能包括:
对联系人信息进行增删改查

表关系分析:

一 概述:数据库中多表之间存在着三种关系:一对一 一对多 多对多 ,这也是系统设计中三种实体关系。
二 建表原则
1 一对多:在多的一方 创建外键指向一得一方的主键
2 多对多:创建一个中间表,中间表里创建至少两个字段作为外键,分别指向多对多双方的主键
3 一对一:
(1)主键对应:一方主键作为另一方主键
(2)唯一外键:一方创建外键字段 指向另一方的主键
三Hibernate通过java对象描述数据表的关系:

一                       对                                           一

   class A{                                                     class B{        
    B b;                                                                A a;
    getter和setter方法                                         getter和setter方法
}                                                               }

一                       对                                           多
class A{                                                        class B{        
    Set<B> b=new HashSet<B>();                      A a;
    getter和setter方法                                         getter和setter方法
}                                                                   }

多                       对                                           多
class A{                                                        class B{        
    Set<B> b;=new HashSet<B>();                         Set<A> a=new HashSet<A>();
    getter和setter方法                                             getter和setter方法
}                                                                   }

多表关系映射配置:

    一   一对多配置
     1. 一对多的一方:
        头标签<set name="" cascade="" inverse=""></set>
            <set>对应着一方实体中关联多方的set集合属性,如果是list集合属性,对应的就是<list>
            <set>元素的属性:
                (1)name(必填) :实体中对应的集合名称
                (2) cascade级联操作属性:
                        <1>级联操作概念:级联操作是指当主控方执行 保存,更新,删除操作时,其关联对象(被控方)也执行相同的操作,简化操作,少写代码
                        <2>cascade属性值:
                                * save-update:级联保存更新
                                        多表操作时,保存一方/主控方(如:客户)的内容,又更新多方(如:联系人)的信息
                                        特性:1》只保存一方的问题
                                                  2》具有方向性,保存一方同时更新另一方
                                        存在情况:当双方都设置了save-update,则会双方都会执行对应关联的sql语句,从而产生多余sql语句。
                                * delete:级联删除,删除一方的同时,也删除多方的信息
                                        概述:使用JDBC删除客户和联系人时,如果有外键的关系是不可以删除的。但Hibernate可以实现这样的功能。
                                                  但使用Hibernate删除有关联关系对象(如,客户)的默认情况,会先将关联关系的外键设置为null,再删掉客户对象。
                                        删除的方式:
                                                1》客户一方不放弃维护外键 inverse="false" ,且没有设置删除级联,属于默认情况时,若直接删除客户则
                                                     会把客户的关联的外键 设置为null再删。
                                                2》客户一方不放弃维护外键 inverse="false",设置了删除级联,若直接删除客户,会把客户关联的(在另一张表的)联系人信息也删掉
                                                3》客户一方放弃维护外键 inverse="true" 时,必须要设置删除级联才可进行删除
                                * all:save-update + delete
                (3)inverse:配置关系是否维护
                        <1>概述:双向关联会产生多余的sql语句,如下面的例子
                                //将2号联系人关联的客户改为2号客户
                                 Customer customer = session.get(Customer.class,2L);
                                 LinkMan linkMan = session.get(LinkMan.class,2L);
                                 //双向关联
                                 linkMan.setCustomer(customer);
                                 customer.getLinkMans().add(linkMan);
                              此代码会出现两个重复(更新外键)的update语句,    
                              原因为:进行双向维护关系时,持久态对象可自动更新到数据库,更新客户时会修改一次外键,
                                            更新联系人时也会修改一次外键,从而产生多余的sql语句
                              解决方案:只需一方放弃外键维护权即可(inverse="true"),也就是说关系不是双方维护的,只需交给一方去维护即可
                                              而一对多时,通常由多方进行关系维护(如老师对学生时,每个学生记住一个老师名字容易于一个老师记住全部学生名字)
                        <2>原则:必须要有一方维护关系,如在 一对多关系中,只能是一方 放弃维护关系(inverse="true"),多方不能放弃维护
                        <3>取值:默认值为false,代表不放弃外键维护权,true为放弃外键维护权
                (4)区分cascade和 inverse:
                     casacde强调的是操作一个对象时,是否还操作其关联对象
                     inverse强调的是外键的维护权
            <set>标签的子标签:
                (1)<key column="" ></key> column对应关联多方(set方)的数据库的外键名称
                (2)<one-to-many class=""/>class 对应关联多方的实体全类名
            一对多中一方的配置示例:
                <set name="linkMans" inverse="true" cascade="save-update">   //放弃维护权,级联保存更新
                    <key column="lkm_cust_id" />
                    <one-to-many class="XXXX.ZZZ.LinkMan"/>   
                </set>
    2. 一对多的多方:
            <many-to-one name="customer" column="lkm_cust_id" class="Customer" cascade="save-update"></many-to-one>
            name:多方实体中关联对象的属性名称
            column:关联实体的在数据库中对应的外键名
            class:关联实体的全类名
            cascade:级联设置
二多对多:
    1. 多对多的配置:
        (1)配置模板:
            <set name="roles" table="sys_user_role" cascade="save-update">
                <key column="user_id"></key>
                <many-to-many class="xx.xxx.Role" column="role_id"></many-to-many>
            </set>
        (2)<set>标签:
            name:关联另一方的集合属性名称
            table:中间表名称
        (3)<key>标签: 
            column:当前对象在中间表的外键名称
        (4)<many-to-many>标签:    
            class:关联另一方的实体全类名
            column:关联另一方对应的外键
    2. 多对多的外键维护问题:
        (1)概述:在多对多的保存操作中,如果进行双向关系维护,就必须要有一方放弃外键维护权。
            原因分析: 因为中间表作为 关系维护纽带
                            若两张表都进行关系维护,则中间表的外键录入每次都不能确定唯一的 主键,会出现 2对1的尴尬,会报错:
            解决方案为:
                1 不书写维护双向关系代码
                2 在某方配置文件中进行 inverse="true"配置
        (2)总结:
                一般是由被动方放弃,如用户对角色,角色是被选中,所以角色要放弃外键维护权。
                但如果进行单向关系维护,就不需任意放弃外键维护权。
    3. 多对多的级联配置:
        多对多进行保存操作时,不可以保存一方,所以必须要进行保存更新级联配置(cascade="save-update")
    4. 多对多的其他操作:
        (1)删除用户关联的角色
             //查询2号用户
             User user = session.get(User.class,2L);
             //查询1号联系人
             Role role=session.get(Role.class,1L);
             //操作集合,相当于操作中间表
             user.getRoles().remove(role);
        (2)将某个用户的角色改选
             //查询2号用户
             User user = session.get(User.class,2L);
             //查询1号联系人
             Role role=session.get(Role.class,1L);
             //查询2号联系人
             Role role2=session.get(Role.class,2L);
             //操作集合,相当于操作中间表
             user.getRoles().remove(role);
             user.getRoles().add(role2);
        (3)给某个用户添加新角色
                 //查询2号用户
                 User user = session.get(User.class,2L);
                 //查询1号联系人
                 Role role=session.get(Role.class,1L);
                 //操作集合,相当于操作中间表
                 user.getRoles().add(role);
一对多 和 多对多配置比较:
    一   (Customer)                                                                            对                                         多(LinkMan)
    private Set<LinkMan>linkMans=new HashSet<LinkMan>();                                         private Customer customer;                 
    <set name="linkMans" inverse="false" cascade="save-update">                             <many-to-one name="customer" column="lkm_cust_id" class="Customer" >
        <key column="lkm_cust_id" />                                                                                </many-to-one>
        <one-to-many class="LinkMan"/>
    </set>
    ***
    多(User)                                                                           对                                         多(Role)
    private Set<Role>roles=new HashSet<Role>();                                                         private Set<User>users=new HashSet<User>(); 

                                                                        中间表只有两个字段:user_id和role_id

    <set name="roles" table="sys_user_role" cascade="save-update">                          <set name="users" table="sys_user_role" inverse="true"> 
        <key column="user_id"></key>                                                                                <key column="role_id"></key>
        <many-to-many class="Role" column="role_id"></many-to-many>                     <many-to-many class="User" column="user_id"></many-to-many>
    </set>                                                                                                                      </set>

)

以上是关于Hibernate知识点复习之三的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate知识点复习之三

Spring知识复习之三

HIBERNATE知识复习记录4-HQL和QBC

Hibernate——实例总结Hibernate对象的状态和ThreadLoacl封闭的session

Hibernate——Hibernate的实现原理总结和对其模仿的demo

日常Geetest滑动验证码(三代canvas版)处理小结(以B站登录验证为例)