Hibernate中 多对一,一对多映射关系分析详解

来源:互联网 发布:用阿里云gpu挖比特币 编辑:程序博客网 时间:2024/05/18 20:31

Hibernate中映射关系主要有以下8种:

1 多对一   站在多的一方思考问题:

关联映射 分析

1表结构:唯一

1-N外键关联 外键设置在从表中

客户信息userinfo , 收件人recipieninfo 

一个客户有多个收件人:

多的一方收件人拥有客户的id


2对象结构

public class Recipieninfo implements java.io.Serializable { 

private int recipienId;
private Userinfo userinfo; //关联1对象的属性
private String recipienname;
private String recipienaddress;
private String recipienphone;
对象为N的对象包含一个1的对象


public class Userinfo implements java.io.Serializable {

 

private int userid;
private String username;
private String userpsw;
private String usernickname;
private String usermail;
private String userimage;
private Date userbirthday;
private int usergender;
private Date usertime;
对象为1 的不做操作

3映射文件结构:

收件人映射文件 Recipieninfo.hbm.xml

<many-to-one name="userinfo" class="beans.Userinfo" fetch="select">
    <column name="userid" not-null="true">
    </column>
</many-to-one>

对于收件人来说是多对一  指明 多对一的一是什么类,关联的外键是: userid

为什么many to one中对应的是 userinfo中的主键:

column默认是对应 Userinfo中的 主键userid 可以通过 property-ref="name"属性配置为其他属性

一般关联主键,用其他属性作为外键约束比较少见,也不常用,而且会带来问题


用1部门 --N员工的例子 代码体现:

代码中,已经体现了关联关系

这里要注意一点:在数据库表有非空约束条件下,或者映射文件中有非空属性为true的时候

1如果数据库表有非空的约束条件,或者映射文件中有非空属性为true,这个关联的动作必须要完成,不然会报一个非空的异常,如果数据库表没有非空约束,映射文件也没有要求,则employee的departmentid为null

2不仅如此,还应该注意sava的顺序,先保存department 然后保存employee 


检索分析:

查询的时候,比如查询一个收件人信息

对象模型关系中,收件人心里关联一个客户信息对象

关系型数据库中,收件人信息里包含了一个客户的id 

我们换一个员工N -- 部门1 的例子看hibernate是如何工作的: 按照id查询 

通过多对象员工的查询,可以得到1对象部门的信息

有个懒加载问题需要提出:

如果在事务提交后,对employee对象进行访问,此时employee对象是托管态的,就会报错

如果想解决此问题:

就需要在事务中,添加初始化代理:
Hibernate.initialize(e.getDepartment); 如上上部分代码。


2一对多 

表结构和多对一是一样的


在对象上

public class Userinfo implements java.io.Serializable {

 

private int userid;
private String username;
private String userpsw;
private String usernickname;
private String usermail;
private String userimage;
private Date userbirthday;
private int usergender;
private Date usertime;
private Set recipieninfos = new HashSet(0);

对象为1的对象包含一个set集合


public class Recipieninfo implements java.io.Serializable { 

private int recipienId;
private Userinfo userinfo; //关联1对象的属性
private String recipienname;
private String recipienaddress;
private String recipienphone;
对象为N的对象包含一个1的对象

                                             

客户映射文件 Userinfo.hbm.xml

<set name="recipieninfos" table="recipieninfo" inverse="true" lazy="true" fetch="select">
    <key>
        <column name="userid" not-null="true"></column>
    </key>
    <one-to-many class="beans.Recipieninfo" />
</set>

对于客户来说 是一对多,指明一对多的多的是一个 recipeininfos类 ,关联recipieninfo表 多的一方的外键是本类中的userid

1 集合的表述:set  表示什么集合 one-to-many class="beans.Recipieninfo"表示集合当中放的是什么

2查询收件人的时候,需要收件人表中的 userid 去做关联,所以需要制定Key为userid  制定外键

代码:

代码在做关联的时候,可以站在1 的角度 也就是客户的角度,添加set集合,也可以站在收件人的角度,添加客户的类。

两种做法产生的sql代码也许会不一致。

我们用部门员工的例子:

一个部门多个员工 

第一种:在员工的对象里添加部门

查询测试:

不难分析出,这样产生的sql语句,只有插入 insert ,先save的是部门,在表中部门没有关联员工的。然后save员工,此时,员工的部门id已经给了,所以只产生了多条insert语句:
第二种:

Set <Employee>  emps = new HashSet<Employee>();
-->
department.setEmps(emps);
-->
s.save(department);
s.save(employee);

可以分析出,我们的employee对象里没有去添加department类
先保存了department.
然后保存employee时,没有部门的信息
所以产生的sql语句应该多几条对employee的update语句:
将1对多的关系反映到数据库的时候,就跟新了employee中的部门id

其实这个更新语句是可以去掉的

项目中总结:

多对一 和一对多,我们在开发的时候,如果多的一方数据量很大,我们应该放弃一对多的维护关系,仅仅只要多对一就可以了。如果我们不需要 1的一方知道它有多少多的一方的对象。就完全可以不使用一对多。

来自自己视频学习的笔记
0 0
原创粉丝点击