hibernate之一对多|多对多案例|关联映射(03)

来源:互联网 发布:淘宝运营浏览器插件 编辑:程序博客网 时间:2024/06/06 19:38

关系映射

实体之间的关系:

一对多:用户和订单 分类和商品 订单和订单项 客户和联系人
多对多:订单和商品 学生和课程 角色和用户
一对一:夫妻 居民和身份证号

表关系设计:

一对多:
在多表上添加一个外键字段.
多对多:
添加一张中间表,表中保留另外两张表的主键作为外键.就可以将多对多拆成两个一对多. 中间表都是多的一方
一对一:
解决方案:
1.两个实体合二为一
2.唯一外键对应(把一张表作为多表,添加外键约束,再在外键上添加唯一约束即可)
3.主键对应(只需要在其中一张表上,给主键添加外键约束即可)

javabean的关系设计:

一对多:
我们可以根据需要:
在一的一方添加多的一方的集合
在多的一方添加一的一方的对象
多对多:
添加一个对方的集合
一对一:
添加一个对方的对象

hibernate中一对多★★

客户和联系人
步骤:
1.新建数据库
create database hibernate03;
use hibernate03;
2.设计javabean
客户:
添加一个联系人的集合
联系人:
添加一个客户的对象

3.编写映射文件
多的一方
many-to-one标签:
name:一的一方在多的一方中对象属性名称
class:一的一方的全限定名
column:外键字段名称

多的一方domain代码:

private Long lkm_id;    private String lkm_name;    private String lkm_gender;    private String lkm_phone;    private String lkm_mobile;    private String lkm_email;    private String lkm_qq;    private String lkm_position;    private String lkm_memo;    //用来表示属于那个客户    //private String lkm_cust_id;    private Customer customer;

多的一方配置文件:

<!-- 配置映射关系             name:一的一方在多的一方中对象属性名称            class:一的一方的全限定名            column:外键字段名称        -->        <many-to-one name="customer" class="com.xx.domain.Customer" column="lkm_cust_id"/>

一的一方,配置文件
set标签:
name属性:多的一方在一的一方中集合属性名称
key标签:
coluomn属性:外键的字段名称
one-to-many标签:
class属性:多的一方的全限定名
代码:

private Long cust_id;    private String cust_name;    private String cust_source;    private String cust_industry;    private String cust_level;    private String cust_phone;    private String cust_mobile;    //表示当前客户拥有的联系人    private Set<Linkman> linkmans = new HashSet<>();

配置文件

<!-- 配置映射关系            name:多的一方在一的一方中集合属性名称名称         -->        <set name="linkmans" cascade="save-update,delete" inverse="true">            <!--                column:外键字段名称              -->            <key column="lkm_cust_id"/>            <!--                 class:多的一方的全限定名             -->            <one-to-many class="com.xx.domain.Linkman"/>        </set> 

注意:
别忘记在核心配置文件中加载两个映射文件

测试

Session session = HibernateUtils.getCurrentSession();        Transaction tx = session.beginTransaction();        //创建1个客户(浩总)        Customer c2 = new  Customer("浩总");        //创建1个联系人(浩秘书)        Linkman l3 = new Linkman("浩秘书");        //双向关联        c2.getLinkmans().add(l3);        l3.setCustomer(c2);        //保存        session.save(c2);//只保存客户的时候,能不能将关联的联系人一并保存呢??不行,报瞬时对象异常错误        tx.commit();

保存客户的同时,将其联系人一并保存:
客户是主体,需要在主体一方的映射文件中设置级联操作 set标签上配置一个属性 cascade=”save-update”

<set name="linkmans" cascade="save-update,delete">

级联操作:

级联:操作主体的时候,顺便将其关联的对象进行同样的操作
级联具有方向性

级联保存更新:
保存客户的同时,将其联系人一并保存:
客户是主体,需要在主体一方的映射文件中设置级联操作 set标签上配置一个属性 cascade=”save-update”

保存联系人的同时,将其客户一并保存:
联系人是主体,需要在主体一方的映射文件中设置级联操作 many-to-one标签上配置一个属性 cascade=”save-update”

级联删除

删除主表中已被引用的数据:
★★先把从表中的指定的外键置为null,然后再删除主表中相应的记录
级联删除:
★★删除客户的同时,将其联系人一并删除:
客户是主体,需要在主体一方的映射文件中设置级联操作 set标签上配置一个属性 cascade=”delete” 或者 cascade=”save-update,delete”
删除联系人的同时,将其客户一并删除
联系人是主体,需要在主体一方的映射文件中设置级联操作 many-to-one标签上配置一个属性 cascade=”save-update,delete”

冗余sql(多余sql)
在测试保存的时候,保存一的一方,然后再保存多的一方,多发送了几条update语句.
他不影响结果.原因:双方都维护了外键.
开发中让一的一方放弃外键维护权
在一的一方的映射文件中的set标签上配置 inverse=”true”

<set name="linkmans" cascade="save-update,delete" inverse="true">

hibernate中多对多★

步骤:
1.创建实体
用户和角色
放入对方的集合
2.编写映射文件
set标签:
name属性:对方的集合属性名称
table属性:中间表表名
key标签
coluomn属性:自己在中间表的外键信息
many-to-many标签
class属性:对方的全限定名
column属性:对方在中间表中的外键信息
注意:在核心配置文件中配置映射文件
3.测试保存
开发中让被动方放弃
在角色的映射文件中配置 inverse=”true”

role类的映射文件配置:

<set name="users" table="sys_user_role" inverse="true"><key column="role_num"/><many-to-many class="com.itheima.domain.User" column="user_num"/></set>

User类的文件配置

<!-- 映射关系            name:对方的集合属性名称            table:中间表表名         -->        <set name="roles" table="sys_user_role" cascade="save-update,delete">            <!-- key标签中column:自己在中间表中的外键字段名称 -->            <key column="user_num"/>            <!--                 class:对方的全限定名                column:对方在中间表中的外键字段名称             -->            <many-to-many class="com.itheima.domain.Role" column="role_num"/>        </set>

级联操作:

多对多 几乎用不上

级联保存更新:(知道 理解)

保存用户的时候将其关联的角色一并保存
用户是主体,需要在主体一方的映射文件中设置级联操作 set标签配置 cascade=”save-update”

级联删除(了解,用不上)

删除用户的同时将其关联的角色一并删除
用户是主体,需要在主体一方的映射文件中设置级联操作 set标签配置 cascade=”save-update,delete”

默认删除:★★

先删除中间表中的相应的记录
然后在删除对应表的相应记录

其他操作:(orm框架)

给用户添加角色
获取角色集合 给集合添加一个角色
给用户删除角色
给用户修改角色

添加角色代码如下:

Session session = HibernateUtils.getCurrentSession();        Transaction tx = session.beginTransaction();        //获取小青        User user = session.get(User.class,1L);        //获取员工        Role role = session.get(Role.class, 3L);        //给小青添加员工角色        user.getRoles().add(role);        tx.commit();

对象导航查询:

前提:
有关联关系
客户1 有几个联系人?
Customer c1 = session.get(Customer.class,1L);
c1.getLinkmans().size();
联系人1的客户名称是啥?
Linkman lk1 = session.get(Linkman.class,1L);
lk.getCustomer().getCust_name();

延迟加载:

用的时候才发送sql语句查询数据
作用:提高效率

★开发中

通过一的一方查询多的一方的时候 一般使用懒加载(默认值)

要想改变
在一的一方的映射关系中配置 lazy属性=false
常见值:
false:理解加载
true:默认值 懒加载

★开发中:

通过多的一方查询一的一方时候,一般都会查询一的一方
需要在多的一方的映射关系上设置 lazy属性:false

扩展:延迟加载:

类级别延迟加载(load)
关闭类级别的延迟加载方式
方式1:在类上加final
方式2:通过配置文件的方式修改 映射文件的class标签上有一个lazy属性 默认:true
关联级别的延迟加载
通过一个对象查询其关联对象是否采用延迟加载

在多的一方的映射关系上lazy属性的取值
false:立即加载
proxy:默认值 代理
是否采用延迟加载取决于一的一方的类级别的延迟加载
若一的一方的类级别的 lazy=true proxy就是延迟加载
若一的一方的类级别的 lazy=false proxy就是立即加载

总结:
实体之间的关系与设计
★★hibernate中的一对多
实体:
根据需要
在一的一方添加多的一方的集合
在多的一方添加一的一方的对象
映射文件:
在多的一方配置
many-to-one标签
name属性
class属性
column属性
在一的一方配置
set标签
name属性
key标签
column属性
one-to-many标签
class属性

级联:
具有方向性 操作主体的时候,将其关联的对象进行相同的操作
级联保存更新
在主体上配置 cascade=”save-update”
级联删除
在主体上配置 cascade=”delete”
默认删除
删除已被引用的一的一方
先把从表中的指定的外键置为null 再删除主表中记录

冗余sql:
让一的一方放弃外键维护权
set标签上 inverse=”true”

★hibernate中的多对多
实体:
放入对象的集合
映射文件
set标签
name属性
table属性
key标签
column属性
many-to-many标签
class属性
column属性

测试保存:
让被动方放弃外键维护权

级联操作几乎用不上
默认删除:
先删除中间表中的相应的记录,再删除相应表中记录

对象导航:

延迟加载:
需要的时候才发送sql语句

通过一的一方查询多的一方的时候,一般使用默认值 延迟加载
通过多的一方查询一的一方时候,一般使用理解加载
在多的一方的上配置 lazy=false