查看“Hibernate笔记 5:实体关联关系”的源代码
←
Hibernate笔记 5:实体关联关系
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:Hibernate]] == 关于 == 数据库中多表之间存在着三种关联关系(一对一、一对多、多对多),用于描述实体数据之间的关系,而这种关系也可以通过对象进行描述。 见: # '''[[Hibernate笔记 5:实体关联关系:一对一]]''' # '''[[Hibernate笔记 5:实体关联关系:一对多]]''' # '''[[Hibernate笔记 5:实体关联关系:多对多]]''' == cascade(级联操作) == “级联操作”:是指当“'''主控方'''”执行“保存”、“更新”或者“删除”操作时,其关联对象(“'''被控方'''”)也执行相同的操作。 1、在映射文件中通过对 cascade 属性的设置来控制是否对关联对象采用级联操作。 2、级联操作对各种关联关系都是有效的。 === 级联属性 === cascade 属性的可选值: # <span style="color: blue">'''all'''</span>:所有情况下均进行关联操作。【即 <span style="color: blue">save-update</span> + <span style="color: blue">delete</span>】 # <span style="color: blue">'''none'''</span>:所有情况下均不进行关联操作。【默认值】 # <span style="color: blue">'''save-update'''</span>:在执行 '''save''' / '''update''' / '''saveOrUpdate''' 时进行关联操作。 # <span style="color: blue">'''delete'''</span>:在执行 '''delete''' 时进行关联操作。 # <span style="color: blue">'''all-delete-orphan'''</span>:当一个节点在对象图中成为'''孤儿节点'''时,删除该节点。 === '''级联的方向性''' === <span style="color: blue;">'''级联是有方向性的'''</span>: 以“一对多”关系为例,“主控方为一端”(通过一端级联操作多端)和“主控方为多端”(通过多端级联操作一端),二者的含义是完全不同的。 示例: * “双向关联:一对多/多对一”; * Customer.hbm.xml、LinkMan.hbm.xml 均配置了级联更新“cascade="save-update"”; : <syntaxhighlight lang="Java" highlight=""> @Test // 删除联系人,并级联删除其客户 public void demo() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 创建一个客户 Customer customer = new Customer(); customer.setCust_name("中国移动"); // 创建三个联系人 LinkMan linkManl = new LinkMan(); linkManl.setLkm_name("老张"); LinkMan linkMan2 = new LinkMan(); linkMan2.setLkm_name("老李"); LinkMan linkMan3 = new LinkMan(); linkMan3.setLkm_name("老王"); //建立关系: linkManl.setCustomer(customer); customer.getLinkMans().add(linkMan2); customer.getLinkMans().add(linkMan3); // 保存 //session.save(linkManl); // 发送几条 insert 语句? //session.save(customer); // 发送几条 insert 语句? //session.save(linkMan2); // 发送几条 insert 语句? tx.commit(); } </syntaxhighlight> 如上代码: # “session.save(linkManl)”:将会产生 '''4''' 条 insert 语句; #: 因为:linkManl 关联了 customer;而 customer 又关联了 linkMan2、linkMan3; # “session.save(customer)”:将会产生 '''3''' 条 insert 语句; #: 因为:customer 关联了 linkMan2、linkMan3,但未关联 linkManl; #: (“linkManl 关联了 customer” ≠ “customer 关联了 linkManl”) # “session.save(linkMan2)”:将会产生 '''1''' 条 insert 语句; #: 因为:linkMan2 未关联其他对象; #: (“customer 关联了 linkMan2” ≠ “linkMan2 关联了 customer”) P.S. “a 关联了 b” '''≠''' “b 关联了 a” == inverse(关系维护) == inverse 属性用于设置“是否由对方维护关联关系”。 可选值:true / false(默认) inverse 作用: # '''级联维护''':配置为 true 的一方所设置的级联将会失效。 #* inverse 的权限在 cascade 之上。 # '''外键维护''':配置为 true 的一方将不再维护关联的外键字段。 #* 维护外键的一方必须拥有对方的实例引用。 === 外键维护 === 通过如下示例,了解 inverse 对外键维护的影响。 “双向关联:一对多”,有配置如下: # Customer.hbm.xml: #: <syntaxhighlight lang="xml" highlight=""> ... <set name="linkMans" cascade="save-update"> <key column="lkm_cust_id"></key> <one-to-many class= "cn.itcast.hibernate.domain.LinkMan"/> </set> ... </syntaxhighlight> # LinkMan.hbm.xml: #: <syntaxhighlight lang="xml" highlight=""> ... <many-to-one name="customer" cascade="save-update" class="cn.itcast.hibernate.domain.Customer" column="lkm_cust_id"/> ... </syntaxhighlight> '''示例1''':未配置 inverse;通过 LinkMan 级联保存。 : <syntaxhighlight lang="Java" highlight=""> @Test // 保存联系人,并级联保存其客户 public void demo1() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 创建客户 Customer customer = new Customer(); customer.setCust_name("中国移动"); // 创建联系人 LinkMan linkMan = new LinkMan(); linkMan.setLkm_name("老张"); // 建立关联关系 linkMan.setCustomer(customer); // 保存 session.save(linkMan); tx.commit(); } </syntaxhighlight> : <syntaxhighlight lang="Java" highlight=""> Hibernate: insert into cst_customer (cust_name, cust_industry, cust_level, cust_phone) values (?, ?, ?, ?) Hibernate: insert into cst_linkMan (1km_name, lkm_phone, lkm_cust_id) values (?, ?, ?, ?) Hibernate: update cst_linkMan set lkm_cust_id where lkm_id=? </syntaxhighlight> 如上,Hibernate 后台执行了一条 update 语句:在级联保存 customer 时将维护 cst_linkMan 表的 lkm_cust_id。 * 由于主控端为“多端”,所以“多端”的 insert 中外键字段不空。 *: 由于 Customer 同时维护外键,所以此处 update 语句是多余的; '''示例2''':Customer 端配置 inverse;通过 LinkMan 级联保存。 : <syntaxhighlight lang="xml" highlight=""> ... <set name="linkMans" cascade="save-update" inverse="true"> <key column="lkm_cust_id"></key> <one-to-many class= "cn.itcast.hibernate.domain.LinkMan"/> </set> ... </syntaxhighlight> : 同样对于上述代码,后台 sql 如下: : <syntaxhighlight lang="Java" highlight=""> Hibernate: insert into cst_customer (cust_name, cust_industry, cust_level, cust_phone) values (?, ?, ?, ?) Hibernate: insert into cst_linkMan (1km_name, lkm_phone, lkm_cust_id) values (?, ?, ?, ?) </syntaxhighlight> 如上,Hibernate 后台将并不执行任何 update 语句。 * 由于主控端为“多端”,所以“多端”的 insert 中外键字段不空。 *: 由于 Customer 放弃维护外键,所以没有 update 语句; '''示例3''':Customer 端配置 inverse;通过 Customer 级联保存。 : <syntaxhighlight lang="xml" highlight=""> ... <set name="linkMans" cascade="save-update" inverse="true"> <key column="lkm_cust_id"></key> <one-to-many class= "cn.itcast.hibernate.domain.LinkMan"/> </set> ... </syntaxhighlight> : <syntaxhighlight lang="Java" highlight=""> @Test // 保存客户,并级联保存其联系人 public void demo2() { Session session = HibernateUtils.openSession(); Transaction tx = session.beginTransaction(); // 创建客户 Customer customer = new Customer(); customer.setCust_name("中国移动"); // 创建联系人 LinkMan linkMan = new LinkMan(); linkMan.setLkm_name("老张"); // 建立关联关系 customer.getLinkMans().add(linkMan); // 保存 session.save(customer); tx.commit(); } </syntaxhighlight> : <syntaxhighlight lang="Java" highlight=""> Hibernate: insert into cst_customer (cust_name, cust_industry, cust_level, cust_phone) values (?, ?, ?, ?) Hibernate: insert into cst_linkMan (1km_name, lkm_phone, lkm_cust_id) values (?, ?, ?, ?) </syntaxhighlight> 如上,Hibernate 后台将并不执行任何 update 语句,但数据库 cst_linkMan 表的外键 lkm_cust_id 为 null。 * 由于主控端为“一端”,所以“多端”的 insert 中外键字段为空。 *: 由于 Customer 放弃维护外键,所以没有 update 语句; *: 最终导致外键字段为 null。 由以上可知,<span style="color: blue; font-size: 120%">'''对于“一对多”关系,通常由“多端”作为主控端,并维护外键'''(inverse 配置在“一端”)</span>。 P.S. “一对多”关系级联更新(保存)时: 1、主控端为“'''一端'''”,sql 执行顺序: <span style="color: blue">'''insert + insert + update'''</span> 2、主控端为“'''多端'''”,sql 执行顺序: <span style="color: blue">'''insert + insert'''</span>
返回至“
Hibernate笔记 5:实体关联关系
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息