1. 一对多映射
1.1 JavaWeb 一对多建表原则
多方表的外键指向一方表的主键;
1.2 编写一对多的 JavaBean
// 客户(一方)和联系人(多方)
// 客户(一方) JavaBean
public class Customer{
private Long cust_id;
private String cust_name;
private Long cust_create_id;
...
// 关联多方
// Hibernate 框架默认的集合是 Set 集合,该集合必须要自己手动初始化
private Set linkmans = new HashSet();
......
}
// 联系人(多方) JavaBean
public class Linkman{
private Long lkm_id;
private String lkm_name;
private String lkm_gender;
...
// 关联一方
// 编写一个对象, 不需要自己 new
private Customer customer;
....
}
1.3 编写一对多的映射配置文件
// Customer.hbm.xml (客户映射配置)
...
// 关联的配置(一方)
// name 表示集合的名称
// column 外键的字段
// Linkman.hbm.xml (联系人映射配置)
...
// 关联的配置(多方)
// name 当前 JavaBean 中的属性
// class 属性的全路径
// column 外键的字段(表)
2. 保存客户和联系人的数据
2.1 双向关联的方式保存数据
public class Demo{
public void fun(){
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 创建客户
Customer c1 = new Customer();
c1.setCust_name("张三");
// 创建联系人
Linkman lk1 = new Linkman();
lk1.setLkm_name("熊大");
Linkman lk2 = new Linkman();
lk2.setLkm_name("熊二");
// 双向关联
c1.getLinkmans().add(lk1);
c1.getLinkmans().add(lk2);
lk1.setCustomer(c1);
lk2.setCustomer(c1);
session.save(c1);
session.save(lk1);
session.save(lk2);
tr.commit();
}
}
2.2 级联保存
级联保存:保存一方,同时可以把关联的对象也保存到数据库中!
级联保存是有方向性的.例如,保存客户时,级联保存联系人;或者,保存联系人时,级联保存客户;
使用 cascade="save-update"
// 保存客户,级联保存联系人
// 需要在客户 Customer.hbm.xml 中配置
pulic class Demo{
pulic class fun(){
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 创建客户
Customer c1 = new Customer();
c1.setCust_name("张三");
// 创建联系人
Linkman l1 = new Linkman();
l1.setLkm_name("熊大");
Linkman l2 = new Linkman();
l2.setLkm_name("熊二");
// 单向关联
c1.getLinkmans().add(l1);
c1.getLinkmans().add(l2);
l1.setCustomer(c1); // 此处,如果没有,报错.
l2.setCustomer(c1); // 此处,如果没有,报错.
// 保存客户
session.save(c1);
tr.commit();
}
}
// 保存联系人,级联保存客户
// 需要在联系人 Linkman.hbm.xml 中配置
column="lkm_cust_id" cascade="save-update"/>
public class Demo{
public class fun(){
Session session = HibernateUtils.getCurrentSession();
Transaction tr = session.beginTransaction();
// 创建客户
Customer c1 = new Customer();
c1.setCust_name("张三");
// 创建联系人
Linkman l1 = new Linkman();
l1.setLkm_name("熊大");
Linkman l2 = new Linkman();
l2.setLkm_name("熊二");
l1.setCustomer(c1);
l2.setCustomer(c2);
// 保存联系人
session.save(l1);
session.save(l2);
tr.commit();
}
}
2.3 级联删除
级联删除也是有方向性的;
// 删除客户时, 删除联系人(一方级联删除多方), 配置 Customer.hbm.xml
2.4 级联的取值和孤儿删除
1. 级联的取值(cascade 的取值)
none: 不使用级联;
save-update: 级联保存或更新;
delete: 级联删除;
delete-orphan: 孤儿删除(只能应用在一对多关系);
all: 除了 delete-orphan 的所有情况;
all-delete-orphan: 包含了 delete-orphan 的所有情况;
2. 孤儿删除
只有在一对多的环境下才有孤儿删除;
在一对多的关系中,可以将一方认为是父方,将多的一方认为是子方;孤儿删除,就是在解除了父子关系的时候,
将子方记录直接删除;
2.5 让某一方放弃外键的维护,为多对多映射做准备: inverse
在修改客户和联系人的关系时,进行双向关联,双方都会维护外键,会产生多余的 SQL 语句.
产生的原因: session 的一级缓存中的快照机制,会让双方都更新数据库,产生了多余的 SQL 语句.
如果不想产生多余的 SQL 语句,那么需要一方来放弃外键的维护, 由多方来维护!
// 放弃外键维护
// Customer.hbm.xml 进行如下配置
// true 表示放弃; 默认值为 false
3. 多对多映射
3.1 多对多建表原则
以用户和角色为例,需要创建三张表: 用户表,角色表,中间表(维护前面两个表的数据);
使用Hibernate 框架,只要编写两个 JavaBean 以及对应的映射配置文件,中间表会自动生成;
多对多映射关系中,必须有一方放弃外键维护;
// 编写用户和角色的 JavaBean
// 用户的 JavaBean
public class User{
private Long user_id;
private String user_name;
private String user_pwd;
...
private Set roles = new HashSet();
}
// 角色的 JavaBean
public class Role{
private Long role_id;
private String role_name;
private String role_desc;
private Set users = new HashSet();
}
// 编写映射配置文件
// 用户的映射配置文件, User.hbm.xml
// 配置多对多
// name 表示集合的名称
// table 表示中间表的名称
// 当前对象在中间表的外键名称
// class : 集合中存入的对象,对象的全路径
// column: 集合中对象,在中间表的外键名称
// 角色的映射配置文件, Role.hbm.xml
参考资料