一、多表关系与多表设计
1、多表关系
一对一:
表的设计原则(分表原则):
优化表的性能
基于语意化分表
一对一的两张表 之间的关系怎么维护?
主外键
相同主键值
一对多:
建表原则:
在一的一方有主键 主表
多的一方有与主表的主键相关联外键 从表
多对多
建表原则:
两种主表(业务表) 中间存在一张中间表
中间表内部维护两个外键
中间表分为两种:
仅仅维护关系的中间表
不仅存在维护关系的外键 还有其他业务字段 例如:订单表 订单项表 商品表
2、多表设计
根据业务设计表模型
分析表的关系: 分方向 看一条(起始表)
一对一设计:
学生表 学籍表
一对多设计:
客户表 联系人表
百度 张三
jd 李四
google 王武
赵六
田七
孙八
多对多设计(权限5张表):
1、通过用户名和密码才能登陆
2、系统有不同的职务
3、不同的职务可以有不同的权限
用户表 职务表(角色表) 权限表(菜单表、功能表)
张三 CEO 查下自己薪资
李四 CTO 查看全部人薪资
王武 CFO 请假
田七 COO 批假
程序员 查看项目进度
查看项目金额
用户角色关系表 角色权限关系表
二、hibernate一对多的配置(重点)
基于的模型 客户与联系人
1、创建实体:
Customer实体
private Long cust_id;
private String cust_name;
private String cust_source;
private String cust_industry;
private String cust_level;
private String cust_phone;
private String cust_mobile;
//当前客户有哪些联系人 一个客户可以包含多个联系人
private Set<Linkman> linkmans = new HashSet<>();
Linkman实体
private Long lkm_id;
private String lkm_name;
private String lkm_gender;
private String lkm_phone;
private String lkm_mobile;
//private Long lkm_cust_id; //当前联系人属于哪一个客户
private Customer customer;
2、单实体的映射配置:
Customer.hbm.xml
<class name="com.itheima.domain.Customer" table="cst_customer">
<id name="cust_id">
<generator class="native"></generator>
</id>
<property name="cust_name"></property>
<property name="cust_source"></property>
<property name="cust_industry"></property>
<property name="cust_level"></property>
<property name="cust_phone"></property>
<property name="cust_mobile"></property>
</class>
Linkman.hbm.xml
<class name="com.itheima.domain.Linkman" table="cst_linkman">
<id name="lkm_id">
<generator class="native"></generator>
</id>
<property name="lkm_name"></property>
<property name="lkm_gender"></property>
<property name="lkm_phone"></property>
<property name="lkm_mobile"></property>
</class>
3、一对多映射关系的配置:
Customer.hbm.xml
<!--
配置一对多 一个Customer 对应多个 联系人
private Set<Linkman> linkmans = new HashSet<>();
Set标签name属性:Set集合的名称 (当前实体使用哪个变量与对方维护关系)
key标签的column:外键的名称
one-to-many标签的class:对方的全限定名
-->
<set name="linkmans">
<key column="lkm_cust_id"></key>
<one-to-many class="com.itheima.domain.Linkman"/>
</set>
Linkman.hbm.xml
<!--
配置多对一
private Customer customer;
name:当前实体使用哪个变量与对方维护关系
class:对方的全限定
column:外键名称
-->
<many-to-one name="customer" class="com.itheima.domain.Customer" column="lkm_cust_id"></many-to-one>
4、一对多的添加操作
级联保存:在保存一方时 于此同时保存与该方有关系的其他对象
cascade="save-update"
级联删除:在删除一方时 于此同时删除与该方有关系的另一方
cascade="delete"
放弃外键维护权
inverse="true"
inverse直译:反转(反转外键维护权) 该方放弃外键维护权
结论:
在开发中 习惯在一的一方配置级联操作(cascade) 在一的一方配置放弃外键维护权(inverse="true")
<set name="linkmans" cascade="save-update,delete" inverse="true">
<key column="lkm_cust_id"></key>
<one-to-many class="com.itheima.domain.Linkman"/>
</set>
5、查询
知识点:延迟加载 lazy="true/false"
查询一的一方 多的一方默认是延迟加载
三、hibernate多对多的配置
模型配置:
user 和 role
User:
private Long user_id;
private String user_code;
private String user_name;
private String user_password;
private String user_state;
//当前该用户具备哪些角色
private Set<Role> roles = new HashSet<>();
Role:
private Long role_id;
private String role_name;
private String role_memo;
//当前该角色被哪些用户使用
private Set<User> users = new HashSet<>();
映射关系的配置:
User.hbm.xml
<set name="roles" table="sys_user_role">
<key column="uid"></key>
<many-to-many class="com.itheima.domain.Role" column="rid"></many-to-many>
</set>
Role.hbm.xml
<set name="users" table="sys_user_role">
<key column="rid"></key>
<many-to-many class="com.itheima.domain.User" column="uid"></many-to-many>
</set>