Hibernate一对多、多对多的关系映射
一对多的建表原则:在多的一方创建一个字段当成外键,然后让这个晚间指向一的一方的主键
多对多的建表原则:在外部创建一张中间表,表中至少有两个字段,分别指向各自表的主键
-
Hibernate操作实体类:
问题:如何让实体类之间明白他们间的关系?
-
以Customer和Linkman为例(一对多)
需要在一的一方有多的一方的集合(Customer中有Linkman的集合)
需求:查找客户及客户下面的所有联系人
拿到Customer也就拿到了下面的所有Linkman的数据
需要在多的一方有一的一方的对象(Linkman中有Customer类的对象)
需求:查找联系人以及联系人所属客户的名字
拿到了联系人的数据,其中包含客户的数据
-
以User和Role为例(多对多)
需要在User类中有Role类的集合,在Role类中有User类的集合
-
以公司和地址为例(一对一)
需要在公司类中有地址类的对象,地址类中有公司类的对象
总结:在卡发中,若是一对多的关系,创建这两个实体类的时候,
在一的一方定义一个多的一方的集合,
在多的一方定义一的一方的对象;
若是多对多的关系,创建实体类的时候,
互相都有对方的集合;
若是一对一的关系,创建实体类的时候,
互相都有对方的对象。
-
配置映射关系(固定方式)
-
一对多(以Customer与Linkman为例)
Customer方:
<setname=”linkmans”>
<keycolumn=”wj_id”></key>
<one-to-manyclass=”cn.itdazhong.domain.Linkman”/>
</set>
Ps: set:配置集合 name:自己里面多的一方的集合属性名column:指定外键名
class:多的一方的全限定名
Linkman方:
<many-to-onename=”customer” class=”cn.itdazhong.domain.Customer” column=”wj_id”>
</many-to-one>
Ps: name:自己里面一的一方对象的属性名class:一的一方的全限定名 column:指定外键名
注意:双方都指定了外键“wj_id”,都会对其进行维护,此时在保存数据时会出现冗余的sql语句,会影响程序性能,所以我们一般让一的一方放弃外键的维护权。(在一的一方设置inverse=“true”)
出现冗余sql语句的原理:
-
配置多对多映射关系
一User与Role为例,注意定义实体类中都有对方类的集合
User方:
<class name=”cn.itdazong.domain.User” table=”sys_user”>
<idname=”user_id” column=”user_id”>
<generatorclass=”native”/>
</id>
<propertyname=”,,,”>
</property>
…//其它属性的配置
<setname=”roles” table=”sys_user_role”>
//name另一方的集合属性名 table中间表的表名
<keycolumn=”user_id”/> //自己在中间表多的外键名
<many-to-manyclass=”cn.itdazhong.domain.Role” column=”role_id”/>
//class另一方实体类的全限定名 column 另一方在中间表的外键名
</set>
</class>
Role方:同上
注意:多对多的时候基本不用级联保存,更应该避免级联删除,被动··的一方放弃外键维护权
(inverse=true)
-
级联
在操作自己数据的时候,会把自己关联的数据一同操作(保存和删除)。
-
保存一的一方数据时,能级联把多的一方的数据也保存起来。
-
删除一的一方数据时,能级联把多的一方的数据也删除掉。
注:级联操作具有方向性,反过来也能实现
在set标签中设置cascade=save-update,delete
Ps:级联的高级应用
测试:有一个客户三个联系人
-
让联系人1关联客户
-
让客户关联联系人2和3。
级联保存操作:
Save(联系人1);//有4条sql语句
Save(客户);//有3条sql语句
Save(联系人2);//有1条sql语句
Save(联系人3);//有一条sql语句
-
对象导航查询
a .根据一个客户,查找客户下面所有联系人的数量
b.根据一个联系人,查找所属客户的名称
企业开发中,一对多要一的一方放弃外键维护
多对多要被动的一方放弃外键维护
Ps:延迟加载
在set标签有lazy属性,用来配置关联级别是否延迟加载。
默认为true(延迟),更改为false(不延迟)。具体使用看业务。