Hibernate关联映射(3) 2016-07-12

接上篇,开始一对多单向关联。由于多对一的单向关联已经在(1)中说过,就不再说了,主要思想就是一对一是使用了more-to-one多对一的特殊形式,利用unique=“true”转换成特殊的一对一来使用。

说明:一对多仍然使用person和address的例子。在一对多单向关联的例子中,一个person可以有多个address,所以在person类中有一个set集合属性的成员变量,集合里面存的是address类型的变量。

一对多外键 单向关联

由于是一个person可以有多个address,所以不能是在person表中增加一列存放address,而是要在address表中增加一列存放preson的主键作为address的外键。(从主键的唯一性考虑,也能达到这种共识)

建议把两种配置粘贴到两个txt中,对比着看

一对多 外键 单向关联配置(如下)

<hibernate-mapping>
    <class name="com.lavasoft.dx._1_n_fk.Person1nfk" table="PERSON_1nfk">
        <id name="personid">
            <generator class="identity"/>
        </id>
        <property name="name"/>
        <property name="age"/>
        <!--映射集合属性,关联到持久化类,inverse="false"表示主控端在Person1nfk端,lazy="false"表示不采用延迟加载-->
        <set name="addresses"
             table="ADDRESS_1nfk"
             cascade="all"
        >
            <!--确定关联的外键列-->
            <key column="personid"/>
            <!--用以映射到关联类属性-->
            <one-to-many class="com.lavasoft.dx._1_n_fk.Address1nfk"/>
        </set>
    </class>
</hibernate-mapping>

<hibernate-mapping>
    <class name="com.lavasoft.dx._1_n_fk.Address1nfk" table="ADDRESS_1nfk">
        <id name="addressid">
            <generator class="identity"/>
        </id>
        <property name="addressdetail"/>
    </class>
</hibernate-mapping>

一对多 连接表 单向关联配置(如下)

<hibernate-mapping>
    <class name="com.lavasoft.dx._1_n_tab.Person1ntab" table="PERSON_1ntab">
        <id name="personid">
            <generator class="identity"/>
        </id>
        <property name="name"/>
        <property name="age"/>
        <!--映射集合属性,join_1ntab是连接表表名-->
        <set name="addresses"
             table="join_1ntab"
                >
            <!--“column="personid"”确定PERSON_1ntab表关联到连接表的外键列名-->
            <key column="personid"/>
            <!--“column="addressid"”关联PERSON_1ntab表的Address1ntab对象的id在连接表中的列名-->
            <!--“unique="true"表示1-N,Person1ntab是1,Address1ntab是多”-->
            <many-to-many
                    column="addressid"
                    unique="true"
                    class="com.lavasoft.dx._1_n_tab.Address1ntab"/>
        </set>
    </class>
</hibernate-mapping>

<hibernate-mapping>
    <class name="com.lavasoft.dx._1_n_tab.Address1ntab" table="ADDRESS_1ntab">
        <id name="addressid">
            <generator class="identity"/>
        </id>
        <property name="addressdetail"/>
    </class>
</hibernate-mapping>

******一对多 外键 单向关联******

同样,由于是单向关联的,address不用特别去关注,就是正常的理解。

对person表,一行一行的看,前面都是普通的写法,很容易就理解了,关键是到<set>标签怎么理解。

由于person类中有一个set集合,所以hibernate设计者将标签叫做set,等到hibernate读到这个标签的时候,就会知道现在配置的这个表是符合一对多的模型的,并且是one-to-more中的one的一方。(很简单,只有one的一方才会把more的一方以set集合的形式存储)

但hibernate不知道的是,这个一对多是使用外键,还是使用连接表,是单向还是双向。

所以hibernate继续往下读,看到name和table就大体知道,将来我要对关联table这个表进行查询,得到的结果赋给叫做addresses的set集合变量。

既然hibernate知道要进行关联查询,那肯定得使用本表的主键与其他表建立联系、搭建桥梁,所以hibernate很聪明的会在table=“”引号中的表内,建一个列,存放本表的主键值,所以我们要做的就是给它命名,这就需要column了。

接下来就是使用one-to-more标签了。其实如果你们没有看到下面的使用连接表的配置的话可能对这个标签没有疑问,就是一个person对用多个address,所以是one-to-more标签。

在这里,我要说一下我发现的规律:就像上面我说的,hibernate看到set标签,只是知道要关联查询了,但不知道是外键查询还是连接表查询(大家可以在写完set后,按alt+/ 看提示中one-to-more与more-to-more都可以)。所以,要规定一下,因为我们知道我想要用外键的方式或连接表的方式,所以根据我们自己的需求,如果是外键方式,就用one-to-more,如果是连接表就用more-to-more。

如果写反了,虽然语法上没问题(我认为),但其实hibernate在运行时是可以知道你是用的外键还是连接表(还是我认为它会知道,起码逻辑上可以实现这样的判断),这是因为我们在one-to-more或more-to-more标签中有class属性,如果hibernate根据class,去找这个类有没有创建对应的表,然后看表名叫什么,与set标签中table的名字以比较就知道了。如果名字一样,那就是外键方式,如果不一样,那说明使用的是连接表。

总之,记住规律就好啦:如果是外键方式,就用one-to-more,如果是连接表就用more-to-more。

******一对多 连接表 单向关联******

有了上面的基础,连接表就好理解啦,还是到set集合后,指定table是连接表的名字,同样key里写在连接表中本表主键所在的列column叫什么名字,根据上面说的规律,我们是连接表的方式,用more-to-more,由于是连接表方式,现在连接表里有personid了,还需要对应的addressid,这也就是more-to-more中column的意思,unique=“true”就把more-to-more变成one-to-more了。

*********一些题外的思考*******

*******胡思乱想,现在有点混乱的就不要看了*****

做为使用者,能看到这里,理解大概的规则和流程,起码看起来不会犯糊涂了,而且有几个小规则掌握后,写起来也好些。

在第一篇感慨过,构建一个想hibernate一样的框架就是一个思维的游戏,只要自己考虑的够周全,能够实现功能,自圆其说就ok,所以在使用别人的框架的时候就很喜欢去想这些东西,会去猜设计者是根据什么规则来约束或引导程序进行判断和运行的。

就像这里(建议大家把两种配置粘贴到两个txt中,对比着看)

作为设计者在设计hibernate时,肯定会想让它更好用:比如你看,我能帮你查找数据,还能把查到的数据根据实体类自动封装成该类的对象,好用吧。当然这得有前提,首先类里面得写上get/set方法,其次,表得有对应的类,这个对应关系就在配置中体现。所以作为设计者,我要知道你哪这个实体类和哪个表是对应的,我就得强制你去给我写配置文件,还得按我的规则来,这样我才能好好分析出来,你才能用的方便。

所以,在考虑要服务大家简化维护表和表之间的关联的时候,由于牵扯太多,就得好好考虑怎么设计配置文件的书写规则了。

还是以现在的一个person对用多个address为例。

设计者作为有经验的编程人员,一看到set集合,就知道要么是一对多要么是多对多。所以设计了标签叫set,name="addresses"是告诉hibernate去该类里面找找addresses变量,看看是不是set集合,有没有对应的get/set方法。而且,要么是一对多要么是多对多的表关系,那你一定得查表,不管你是查address表还是连接表,总之得查表吧,那行我把table属性也放到set标签内。

但是到这时,我设计的hibernate还是没法确定你到底是一对多还是多对多,但我不管是那种,你都得在两个表之间建立联系才能关联查询啊,所以不管你这个table写的表名是address表还是连接表,你都得把person表的主键作为table所代表的表的外键,这样才能联系起来进行关联查询啊。而且,我知道一定是person表的主键作为外键列,所以就起个特定的标签就做key吧,你就不用写把哪一列作为外键列了,我知道是主键列了,你就给我说我的hibernate帮你把主键放到table那个表里后列名叫什么。所以key里只用写column就可以了。

现在无论是一对多还是多对多,你们共同的部分我都把规则指定好了,像表明table啊,列名啊column,现在就要确定你到底是一对多还是多对多了,就通过one-to-more与more-to-more来区分。

如果你写的是one-to-more,那好,你就是用的一对多,而且是外键关联(多对多只能通过连接表,而一对多的连接表关联就是多对多的特例)。

你用的是一对多的外键关联的话,那你的table="ADDRESS_1nfk",这个ADDRESS_1nfk就是address表了。而我作为设计者,得考虑多种情况,比如可能他配置错了table名字,根本就没找到这个表名,这种简单,直接报错。再一个就尴尬了,找到了ADDRESS_1nfk这个表名,但这个表对应的却不是address实体类,我作为设计者必须考虑到这种情况,所以我在one-to-more标签中加上class属性。如果找不到table对应的表还好,直接报错,如果找到的话,也得先等等,我得判断一下,你这个表对应的实体类是不是class=“”中的类。如果这一步校验成功,那好,我确定你就是我要找的address表,我给你增加一列personid,作为外键,到时候我会把personid和你address表关联起来查询。

再看如果写的是more-to-more,那我的hibernate就会知道你是多对多,虽然你可能会通过我设计的unique=“true”把more-to-more变成实际上的one-to-more,不过没关系,关键在于你是用连接表关联查询。作为连接表就得有既有你person表的主键也有address表的主键。

所以同样的道理,有了key标签。然而address表的主键怎么设置进连接表中呢,因为是的hibernate是在你写了more-to-more标签之后才知道是用连接表,在此之前还不能对连接表设置,所以就在more-to-more标签中设置吧,就有了column="addressid",这样就算是在连接表中加了一列。但是我的hibernate只知道要加一列,而且我的hibernate已经知道是连接表了,肯定表里存的是各表的主键,唯一的问题就是不知道addressid这一列的数据从哪里来。所以有了class属性。我的hibernate找到class对应的类,然后看这个类有没有创建对应的表,有的话把表的主键拿到连接表的addressid列中。

这里的class就没有上面one-to-more中那样帮助hibernate判断的功能啦,因为使用more-to-more后,hibernate知道是用连接表,就会看table="join_1ntab"这个名字是否被别的表占用了,如果有的话(就有两种选择,是直接覆盖还是选择报错),如果没有的话,那我的hibernate正好帮你创建这么一个连接表。

下面是参考的资料:

http://lavasoft.blog.51cto.com/62575/39398/  强烈推荐先看,博文写了14种情况下的配置,我就是看了这个再结合其他资料摸索的规律

http://blog.sina.com.cn/s/blog_62f0eaa80101bpaf.html

http://blog.sina.com.cn/s/blog_62f0eaa80101bpah.html

http://blog.csdn.net/sanjy523892105/article/details/7061602

http://blog.csdn.net/linminqin/article/details/6324567

http://blog.csdn.net/jialinqiang/article/details/8704538

时间: 2024-08-25 04:32:29

Hibernate关联映射(3) 2016-07-12的相关文章

第六章 Hibernate关联映射

第六章 hibernate关联映射一.本章知识点分为2部分:1.关联关系:单向多对一关联关系,双向一对多关联关系(含一对多关联关系),多对多关联关系2.延迟加载:类级别加载策略,一对多加载策略,多对一加载策略二.关联关系1.单向多对一关联关系1.1.概念(什么是单向多对一关联关系,举例说明)  以部门(Dept).Emp(员工)为例: 从员工角度看部门,是多个员工都在一个部门,这就叫单向 如部门编号为20的部门下可以有n个员工(如scott账户下emp表 empno 为7369,7566,778

http://www.cnbc.com/2016/07/12/tensions-in-south-china-sea-to-persist-even-after-court-ruling.html

http://www.cnbc.com/2016/07/12/tensions-in-south-china-sea-to-persist-even-after-court-ruling.html The judgment is not important. Arbitration that is only agreed on by one party is nothing more than toilet paper. This is my land; why should I let som

hibernate关联映射

本文可作为北京尚学堂马士兵hibernate课程的学习笔记. hibernate的映射,主要分为一对一,一对多,多对一,多对多,同时还要单向与双向的区别. OK,不要纠结于名字,我们开始看例子. 一对一单向 老公是一个实体,老婆也是一个实体. 一个老公只有一个老婆,同时一个老婆也只有一个老公. 上面的关系就叫做一对一. 什么叫单向呢. 看代码: package com.bjsxt.hibernate; @Entity public class Husband { private int id;

hibernate关联映射【一对一主键】

从三个部分介绍Hibernate一对一主键关联映射. 1.基本介绍2.代码展示3.总结注意  1.基本介绍 一对一关联有两种情况: 单向一对一主键关联.双向一对一主键关联.一对一主键关联: 是指两个表之间通过主键形成一对一的映射,例如,每个公民只允许拥有一个身份证,公民与身份证就是一对一的关系,定义两张表,一张People表,一张IdCard表,People表的id既是该表的主键也是该表的外键,并且People的id也就是IdCard的id, 2.代码 单向一对一主键关联:people表的id既

Hibernate关联映射 映射文件的配置

一:多对一单向关联 首先我们必须创建两个实体类 例如:Dept类 public class Dept { private Integer deptNo; private String dName; private String loc; private Set<Employee> emps=new HashSet<Employee>(); Employee类 public class Employee { private Integer empno; private String

Hibernate关联映射关系

一.双向一对多关联映射关系:当类与类之间建立了关联,就可以方便的从一个对象导航到另一个或另一组与它关联的对象(一对多双向关联和多对一双向关联是完全一样的) 1.1创建实体类(Emp(员工),Dept(部门)) /* * 员工实体类 */public class Emp { private Integer empId; //员工编号 private String empName; //员工姓名 private Dept dept; //所处部门 //get(),set()方法省略 } /* * 部

Hibernate 关联映射

ORM(Object Relational Mapping)对象/关系映射 说到Hibernate的关联映射就必须要提一提ORM了.那么ORM是什么呢,其是一种持久化技术,他在对象模型和关系型数据库之间建立对象关系,通过操作JavaBean对象来完成对数据库的操作! 注意:ORM是概念化的并不是实际存在的,可以理解为其是一种编程思想,而Hibernate框架就是该思想的实现产品! 配置Po对象(和数据表绑定的持久化对象)的关联关系 从上面说到ORM可以在对象模型和数据库之间建立对应关系而在Hib

Hibernate关联映射(单项多对一和一对多、双向一对多)

最近总是接触着新的知识点来扩展自己的知识面:不停的让自己在原地接触天空的感觉真的很美好!!!革命没有成功,程序员的我们怎么能不努力呢...... 一.用员工和部门来剖析关联映射的原理. 1)从这张截图可以看出我会站在员工的角度讲述:(单向关联) 关系:(多个员工对应一个部门)多对一的关系 意味:多个Emp对象只会引用一个Dept对象 方法:在Emp类中定义一个Dept类型属性,来引用所有关联的Dept对象 eg. 第一步建立两个实体类省略 第二步建立大配置 <?xml version='1.0'

hibernate关联映射(一对多)

这篇博客将会给大家带来hibernate的关联映射的学习.在现实生活中,不仅只是一对一的映射关系,更多的是一对多,多对多等. 一对多单项关联映射 这里我以网盘为例,一个用户可以拥有多个文件,及用户和文件之间是一对多的关系. user实体类: public class Users { private int uid; private String uname; //用户上传的所有文件 // one方 可以获取 many方 private Set<UpFile> files = new HashS

hibernate关联映射之一对多&amp;多对一

package loaderman.b_one2Many; import java.util.HashSet; import java.util.Set; public class Dept { private int deptId; private String deptName; // [一对多] 部门对应的多个员工 private Set<Employee> emps = new HashSet<Employee>(); public int getDeptId() { re