一对多、多对一
在表中表达:外键

在对象中的表达:集合(使用Set集合)

在orm元数据文件中配置:
在上述实体中添加了相应的集合(Set<LinkMan>)跟对象(Customer)属性后,就得在orm元数据中去配置这两个属性了
在一的一方配置(即拥有集合的一方)
在Customer.hbm.xml中写入
<!--
name: 填写集合属性名
column: 外键名(数据库表中的外键名)
class: 与我关联的类的名称,即多的一方的实体类名
-->
<set name="linkman">
<!-- 要指定的外键列名 -->
<key column="lkm_cust_id"></key>
<!-- 指定对应的关系:一对多 -->
<one-to-many class="LinkMan" />
</set>
在多的一方配置
在LinkMan.hbm.xml中写入
<!--
name: 属性名
column: 外键列名
class: 与我关联的类的名称,即一的一方的实体类的名称
-->
<many-to-one name="customer" column="lkm_cust_id" class="Customer">
</many_to_one>
一对多关系操作
创建客户跟联系人,并指定客户对应的联系人
public void test(){
// 获取session
Session session = HBUtils.CurrentSession();
// 获取事务并开启
Transaction tx = session.beginTransaction();
// -------------------------------------
// 创建客户跟联系人
Customer customer = new Customer();
customer.setCust_name("Sacrtlett");
// 创建客户
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("Eric Jin");
LinkMan linkMan1 = new LinkMan();
linkMan1.setLkm_name("taylor");
// 添加关系
customer.getLinkMens().add(linkMan);
customer.getLinkMens().add(linkMan1);
linkMan.setCustomer(customer);
linkMan1.setCustomer(customer);
// 保存
session.save(customer);
session.save(linkMan);
session.save(linkMan1);
// -------------------------------------
// 提交事务
tx.commit();
}
为客户添加联系人
public void test(){
// 获取session
Session session = HBUtils.CurrentSession();
// 获取事务并开启
Transaction tx = session.beginTransaction();
// -------------------------------------
// 获取要操作的客户
Customer c = session.get(Customer.class, 1L);
// 创建联系人
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("mike");
// 将联系人添加到客户,将客户设置到联系人中
c.getLinkMens().add(linkMan);
linkMan.setCustomer(c);
// 保存
session.save(linkMan);
// -------------------------------------
// 提交事务
tx.commit();
}
解除客户与联系人的关系
public void test(){
// 获取session
Session session = HBUtils.CurrentSession();
// 获取事务并开启
Transaction tx = session.beginTransaction();
// -------------------------------------
// 获取要操作的客户
Customer c = session.get(Customer.class, 1L);
// 获取要移除的联系人
LinkMan lm = session.get(LinkMan.class, 1L);
// 将联系人从客户集合集合中删除
c.getLinkMens().remove(lm);
lm.setCustomer(null);
// -------------------------------------
// 提交事务
tx.commit();
}
多对多
在表中表达

上面的图片中,通过第三方的一张表将Author表跟Book表联系了起来,而这第三方表最少应该有两列,一列是与Author表的id关联的外键,一列是与Book表关联的外键。
在上图中,第三张表的Author_id的跟Book_id中1对应了1,1还对应了2,这表示大灰狼参与编写了java编程跟python精通这两本书。而3也与1对应了,这表示参与了编写java精通的还有大老虎,
一个作者可以编写多本书,而一本书也可以由多个作者编写,这很好的体现了多对多的思想
在对象中表达

在orm元数据文件中配置:
由于都是多的一方,所以两方的配置应该是一模一样的,只是需要把相应的参数修改一下就可以了
在Author.hbm.xml中写入
<!--
name: 实体勒种集合的属性名
tables: 配置第三张表的表名
key下面的column: 外键名,第三张表与我关联的外键名
class: 与我关联的类名,即另外一方的实体类的类名
many-to-many: 我引用别人的外键,即第三张表与另外一方关联的外键名
-->
<set name="book" tables="sys_author_book">
<!-- 要指定的外键名 -->
<key column="author_id"></key>
<!-- 指定对应关系 -->
<many-to-many class="Book" column="book_id" />
</set>
在Book.hbm.xml中写入
由于都是多的一方,所以只需要把相应的参数做一下修改即可
<set name="author" tables="sys_author_book">
<!-- 要指定的外键名 -->
<key column="book_id"></key>
<!-- 指定对应关系 -->
<many-to-many class="Author" column="author_id" />
</set>
多对多关系操作
添加关联
public void test(){
// 获取session
Session session = HBUtils.CurrentSession();
// 获取事务并开启
Transaction tx = session.beginTransaction();
// -------------------------------------
// 创建两个Author
Author a1 = new Author();
a1.setAuthor_name("大灰狼");
Author a2 = new Author();
a2.setAuthor_name("大熊猫");
// 创建两个Book
Book b1 = new Book();
b1.setBook_name("java编程");
Book b2 = new Book();
b2.setBook_name("python精通");
// 作者关系表达
a1.getBook().add(b1);
a1.getBook().add(b2);
a2.getBook().add(b1);
// 书籍关系表达
/*
在这里应该注意,在上面a1跟a2已经对第三方表进行了维护,已经往第三张表里面
插入数据了,如果b1跟b2再去维护,在往是第三张表里面插入数据就会出错,所以
不需要再让书籍去维护,硬是要维护也行,只需要去书籍的orm配置文件中将inverse
配置成true放弃维护就可以了
*/
// 保存
session.save(a1);
session.save(a2);
session.save(b1);
session.save(b2);
// -------------------------------------
// 提交事务
tx.commit();
}
结论:将来在开发中,如果遇到多对多关系,一定要选择一方放弃维护选择放弃谁要根据业务需求来定,比如要给作者指定书籍,那么就给作者维护。如果要为书籍配备作者,就是指定书籍维护
为作者添加书籍
public void test(){
// 获取session
Session session = HBUtils.CurrentSession();
// 获取事务并开启
Transaction tx = session.beginTransaction();
// -------------------------------------
// 获取Author
Author a = session.get(Author.class, 1L);
// 创建书籍
Book b = new Book();
b.setBook_name("c语言入门");
// 将书籍与作者关联
a.getBook().add(b);
// 保存
session.save(b);
// -------------------------------------
// 提交事务
tx.commit();
}
解除某个作者的一本书籍
public void test(){
// 获取session
Session session = HBUtils.CurrentSession();
// 获取事务并开启
Transaction tx = session.beginTransaction();
// -------------------------------------
// 获取Author
Author a = session.get(Author.class, 1L);
// 获取书籍
Book b = session.get(Book.class, 1L);
// 将书籍从角色中移除
a.getBook().remove(b);
// -------------------------------------
// 提交事务
tx.commit();
}
配置级联跟是否维护
级联操作:cascade
有的时候觉得像 ssession.save(b) session.save(a) 既要将Author的对象持久化又要将Book对象持久化太麻烦了,于是想在持久化作者的时候顺便把书籍也持久化,这时就可以使用cascade级联操作
级联参数
save-update: 级联保存更新
delete: 级联删除
all: 相当于 save-update + delete
一对多中使用级联
在主表设置:
<set name="linkMens" cascade="save-update">
<!-- 要指定的外键列名 -->
<key column="lkm_cust_id"></key>
<!-- 指定对应关系 -->
<one-to-many clss="linkMan" />
</set>
也可以在从表设置:
<many-to-one name="customer" column="lkm_cust_id" class="Customer" cascade="all"></many-to-one>
在设置之后就可以在session.save(a)的时候也session.save(b)了
注意: 一般不建议设置cascade的属性为delete,太危险!
多对多中使用级联
<set name="author" tables="sys_author_book" cascade="all">
<!-- 要指定的外键名 -->
<key column="book_id"></key>
<!-- 指定对应关系 -->
<many-to-many class="Author" column="author_id" />
</set>
注意:在多对多中一般不建议使用级联
配置关系是否维护
在操作一对多或者多对多的时候,两方都会对外键进行维护,这显得很多余,降低效率,甚至在多对多中都去维护还会报错!只需要由一方维护就可以了,这时可以通过设置inverse来让一方放弃维护而全权交由对方去维护
inverse属性:
true:当前配置的对象不维护关系,全权交由另一方维护
false(默认):当前配置的对象自己维护关系
一对多
<!-- 设置用户对象不维护,交由联系人对象维护 -->
<set name="linkMens" inverse="true">
<!-- 要指定的外键列名 -->
<key column="lkm_cust_id"></key>
<!-- 指定对应关系 -->
<one-to-many clss="linkMan" />
</set>
当设置了不再维护后,那么客户维护联系人的代码可以省略
// c.getLinkMans().add(lm1);
// c.getLinkMans().add(lm2);
注意:只能是一的一方放弃维护,多的一方含有外键,不能自己放弃自己
如果放弃了维护,那么在一的一方在删除数据时,由于没有维护,会不允许删除,因为已经被联系人关联了,这时必须使一的一方也维护
多对多
多对多不管哪一方都能放弃维护,至于具体是哪一方放弃维护,要根据项目的实际情况来定
<!-- Book放弃维护,交给Author去维护 -->
<set name="author" tables="sys_author_book" inverse="true">
<!-- 要指定的外键名 -->
<key column="book_id"></key>
<!-- 指定对应关系 -->
<many-to-many class="Author" column="author_id" />
</set>
