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 中配置 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