一、一对多
1、关系表达
1)实体中的表达
一对多:用set集合属性表示
private Set<LinkMan> linkMans = new HashSet<LinkMan>();
多对一:用“一”的引用表示
private Customer customer;
2)orm中的表达
一对多:name:set集合属性名
column:外键列名
class:与“我”相关的对象完整类名
<set name="linkMans" cascade="all">
<key column="lkm_cust_id"></key>
<one-to-many class="LinkMan"/>
</set>
多对一:name:属性引用名
column:外键列名
class:与“我”相关的对象完整类名
<many-to-one name="customer" class="Customer" column="lkm_cust_id" cascade="delete"></many-to-one>
2、关系操作
@Test
public void text() {
Session session = HibernateUtils.openSession();
Transaction ts = session.beginTransaction();
//-----------------------------------------------------------------
Customer customer = new Customer();
customer.setCust_name("百度");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("李四");
linkMan.setCustomer(customer);
LinkMan linkMan2 = new LinkMan();
linkMan2.setLkm_name("张三");
linkMan2.setCustomer(customer);
customer.getLinkMans().add(linkMan);
customer.getLinkMans().add(linkMan2);
session.save(customer);
session.save(linkMan);
session.save(linkMan2);
//-----------------------------------------------------------------
ts.commit();
session.close();
}
3、级联操作cascade
一对多:
<!--
级联操作:cascade
save-update:级联保存更新
delete:级联删除
all:save-update + delete
-->
<set name="linkMans" cascade="all">
<key column="lkm_cust_id"></key>
<one-to-many class="LinkMan"/>
</set>
多对一:
<many-to-one name="customer" class="Customer" column="lkm_cust_id" cascade="delete"></many-to-one>
实际开发中不建议使用delete
4、关系维护inverse
inverse属性:配置关系是否维护
true:不维护
false:(默认值)维护
<set name="linkMans" inverse="true">
<key column="lkm_cust_id"></key>
<one-to-many class="LinkMan"/>
</set>
注意:不维护可以优化操作。(少了修改外键值语句)
原因:如果“一”的一方维护关系,当添加“一”后,再添加set集合中的对象后,会 手动修改每个外键值。
但是“多”的一方会自动维护关系,也就是说“多”的一方指定引用对象后,外键 值会自动填好,没必要再修改一次。
对“一”操作:
(1)增加:如果set集合中有对象
维护:不会自动保存set集合中的对象,但是会报错
不维护:不自动保存set集合中的对象,不会保存
(2)删除:
维护:删除成功,先把外键中对应的值改为null,然后删除
不维护:删除不了,因为有外键约束
(3)查询:
不管维护与否都会查询set中的对象
(4)修改主键值:
无论维护与否都修改失败
二、多对多
1、关系表示
1)对象中的表示
两个对象各添加一个set集合属性
角色对象中添加用户集合属性:
private Set<User> users = new HashSet<User>();
用户对象中添加角色集合属性:
private Set<Role> roles = new HashSet<Role>();
2)orm元数据中的表示
两个orm元数据中的配置属性一样
<!--
name:本对象集合属性名
table:多对多关系表
key:
column:本对象外键列名
many-to-many:
class:多对多关系的另外一个类
column:另一个类的外键列名
-->
<set name="roles" table="user_role">
<key column="user_id"></key>
<many-to-many class="Role" column="role_id"></many-to-many>
</set>
2、关系操作
如下代码出现的问题:
//插入多对多关系
@Test
public void test() {
Session session = HibernateUtils.openSession();
Transaction ts = session.beginTransaction();
//------------------------------------------------------------------
Role role1 = new Role();
role1.setRole_name("江湖人");
Role role2 = new Role();
role2.setRole_name("年轻人");
User user1 = new User();
user1.setUser_name("张无忌");
User user2 = new User();
user2.setUser_name("赵敏");
role1.getUsers().add(user1);
role1.getUsers().add(user2);
role2.getUsers().add(user1);
role2.getUsers().add(user2);
user1.getRoles().add(role1);
user1.getRoles().add(role2);
user2.getRoles().add(role1);
user2.getRoles().add(role2);
session.save(user1);
session.save(user2);
session.save(role1);
session.save(role2);
//------------------------------------------------------------------
ts.commit();
session.close();
}
因为多对多两方都维护了关系,相当于插入了两次,由于主键约束,所以出错了
解决方法:
1)删除:
role1.getUsers().add(user1);
role1.getUsers().add(user2);
role2.getUsers().add(user1);
role2.getUsers().add(user2);
2)关闭其中一方的关系维护
3、关系维护inverse
多对多关系必须关闭其中一方的关系维护,关闭哪一方看业务
比如多读多关系:用户和角色
应该关闭角色的关系维护。