1、多表设计(总结)
(1)多表关系
1)一对一:
表的设计原则(分表原则):
优化表的性能
基于语意化分表
一对一的两张表 之间的关系怎么维护?
主外键
相同主键值
2)一对多:
建表原则:
在一的一方有主键 主表
多的一方有与主表的主键相关联外键 从表
3)多对多
建表原则:
两种主表(业务表) 中间存在一张中间表
中间表内部维护两个外键
中间表分为两种:
仅仅维护关系的中间表
不仅存在维护关系的外键 还有其他业务字段 例如:订单表 订单项表 商品表
(2)多表设计
1)根据业务设计表模型
2)分析表的关系: 分方向 看一条(起始表)
3)一对一设计:
学生表 学籍表
4)一对多设计:
客户表 联系人表
百度 张三
jd 李四
google 王武
赵六
田七
孙八
5)多对多设计(权限5张表):
1、通过用户名和密码才能登陆
2、系统有不同的职务
3、不同的职务可以有不同的权限
用户表 职务表(角色表) 权限表(菜单表、功能表)
张三 CEO 查下自己薪资
李四 CTO 查看全部人薪资
王武 CFO 请假
田七 COO 批假
程序员 查看项目进度
查看项目金额
用户角色关系表 角色权限关系表
2、Hibernate一对多的操作
实体类结构:
//客户表:
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> linkmanSet = new HashSet<Linkman>();//多的一方集合
//联系人表
private long lkm_id;//'联系人编号(主键)',
private String lkm_name;// '联系人姓名',
private String lkm_gender;//'联系人性别',
private String lkm_phone;//'联系人办公电话',
private String lkm_mobile;//'联系人手机',
private String lkm_email;// '联系人邮箱',
private String lkm_qq;//'联系人qq',
private String lkm_position;// '联系人职位',
private String lkm_memo;//'联系人备注',
//lkm_cust_id` bigint(32) NOT NULL COMMENT '客户id',
private Customer customer;//一的一方对象
配置映射关系:
<!--客户表关系映射-->
<hibernate-mapping>
<class name="com.itheima.domain.Customer" table="cst_customer">
<id name="cust_id" column="cust_id">
<generator class="native"></generator>
</id>
<property name="cust_name" column="cust_name"></property>
<property name="cust_source" column="cust_source"></property>
<property name="cust_industry" column="cust_industry"></property>
<property name="cust_level" column="cust_level"></property>
<property name="cust_phone" column="cust_phone"></property>
<property name="cust_mobile" column="cust_mobile"></property>
<!--
配置一对多 一个Customer 对应多个 联系人
private Set<Linkman> linkmans = new HashSet<>();
Set标签name属性:Set集合的名称 (当前实体使用哪个变量与对方维护关系)
key标签的column:外键的名称
one-to-many标签的class:对方的全限定名
级联保存:在保存一方时 于此同时保存与该方有关系的其他对象
cascade="save-update"
级联删除:在删除一方时 于此同时删除与该方有关系的另一方
cascade="delete"
放弃外键维护权
inverse="true"
inverse直译:反转(反转外键维护权) 该方放弃外键维护权
查询:延迟加载 lazy="true/false"
查询一的一方 多的一方默认是延迟加载
结论:
在开发中 习惯在一的一方配置级联操作(cascade) 在一的一方配置放弃外键维护权
-->
<set name="linkmanSet" cascade="save-update,delete" inverse="true">
<key column="lkm_cust_id"></key>
<one-to-many class="com.itheima.domain.Linkman"></one-to-many>
</set>
</class>
</hibernate-mapping>
<!--联系人表关系映射-->
<hibernate-mapping>
<class table="cst_linkman" name="com.itheima.domain.Linkman">
<id name="lkm_id" column="lkm_id">
<generator class="native"></generator>
</id>
<property name="lkm_name" column="lkm_name"></property>
<property name="lkm_gender" column="lkm_gender"></property>
<property name="lkm_phone" column="lkm_phone"></property>
<property name="lkm_mobile" column="lkm_mobile"></property>
<property name="lkm_email" column="lkm_email"></property>
<property name="lkm_qq" column="lkm_qq"></property>
<property name="lkm_position" column="lkm_position"></property>
<property name="lkm_memo" column="lkm_memo"></property>
<!--
配置多对一
private Customer customer;
name:当前实体使用哪个变量与对方维护关系
class:对方的全限定
column:外键名称
-->
<many-to-one name="customer" column="lkm_cust_id" class="com.itheima.domain.Customer"></many-to-one>
</class>
</hibernate-mapping>
配置核心参数:
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping resource="com/itheima/domain/Customer.hbm.xml"/>
<mapping resource="com/itheima/domain/Linkman.hbm.xml"/>
</session-factory>
</hibernate-configuration>
测试:
public class OneToManyTets {
//对象导航查询
@Test
public void test3(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = session.get(Customer.class, 5l);
Set<Linkman> linkmanSet = customer.getLinkmanSet();
for(Linkman linkman : linkmanSet){
System.out.println(linkman.getLkm_id()+" "+linkman.getLkm_name());
}
//测试导航对象
Linkman linkman = session.get(Linkman.class, 1l);
System.out.println("Customer:"+customer.getCust_name());
System.out.println("Linkman:"+linkman.getLkm_name());
transaction.commit();
HibernateUtils.close(session);
}
//级联删除
@Test
public void test2(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//Linkman linkman = session.get(Linkman.class, 6l);
//session.delete(linkman);
Customer customer = session.get(Customer.class, 9l);
session.delete(customer);
transaction.commit();
HibernateUtils.close(session);
}
//一对多存储、级联保存
@Test
public void test1(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer();
Linkman linkman1 = new Linkman();
Linkman linkman2 = new Linkman();
customer.setCust_name("CF");
linkman1.setLkm_name("盖比");
linkman2.setLkm_name("拉伦多");
//维护关系
customer.getLinkmanSet().add(linkman1);
customer.getLinkmanSet().add(linkman2);
linkman1.setCustomer(customer);
linkman2.setCustomer(customer);
//保存
session.save(customer);
//session.save(linkman1);
//session.save(linkman2);
transaction.commit();
HibernateUtils.close(session);
}
}
3、Hibernate多对多的操作
实体类结构
//用户实体类
private long user_id;//'用户id',
private String user_code;// '用户账号',
private String user_name;// '用户名称',
private String user_password;// '用户密码',
private String user_state;// '1:正常,0:暂停',
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>();//多对多集合
配置映射关系
<!--用户关系配置-->
<hibernate-mapping>
<class name="com.itheima.domain.User" table="sys_user">
<id name="user_id" column="user_id">
<generator class="native"></generator>
</id>
<property name="user_code" column="user_code"></property>
<property name="user_name" column="user_name"></property>
<property name="user_password" column="user_password"></property>
<property name="user_state" column="user_state"></property>
<!-- 配置多对多
name:set集合的名称
key的column:当前实体在中间表中的外键名称(别人引用我的外键)
many-to-many的class:对方的全限定名
many-to-many的column:代表对方的外键名称(我引用别人的外键)
table:中间表名称
-->
<set name="roles" table="sys_user_role" inverse="true">
<key column="user_id"></key>
<many-to-many class="com.itheima.domain.Role" column="role_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
<!--角色关系配置-->
<hibernate-mapping>
<class name="com.itheima.domain.Role" table="sys_role">
<id name="role_id" column="role_id">
<generator class="native"></generator>
</id>
<property name="role_name" column="role_name"></property>
<property name="role_memo" column="role_memo"></property>
<set name="users" table="sys_user_role">
<key column="role_id"></key>
<many-to-many class="com.itheima.domain.User" column="user_id"></many-to-many>
</set>
</class>
</hibernate-mapping>
配置核心配置参数
<hibernate-configuration>
<session-factory>
<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
<property name="hibernate.connection.username">root</property>
<property name="hibernate.connection.password">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">true</property>
<property name="hibernate.format_sql">true</property>
<property name="hibernate.hbm2ddl.auto">update</property>
<mapping resource="com/itheima/domain/Role.hbm.xml"/>
<mapping resource="com/itheima/domain/User.hbm.xml"/>
</session-factory>
</hibernate-configuration>
测试
public class ManyToManyTest {
@Test
public void test02(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//给用户添加角色
User user = session.get(User.class, 9l);
Role role = session.get(Role.class,13l);
role.getUsers().add(user);
session.save(role);
transaction.commit();
HibernateUtils.close(session);
}
@Test
public void test01(){
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
//添加用户和角色
User user01 = new User();
User user02 = new User();
Role role01 = new Role();
Role role02 = new Role();
user01.setUser_name("魔兽世界");
user02.setUser_name("LOL");
role01.setRole_name("摩登莫西");
role02.setRole_name("路西多亚");
user01.getRoles().add(role01);
user02.getRoles().add(role02);
role01.getUsers().add(user01);
role02.getUsers().add(user02);
session.save(role01);
session.save(role02);
session.save(user01);
session.save(user02);
transaction.commit();
HibernateUtils.close(session);
}
}