1.Hibernate的一对多
(1)表与表之间关系
一对多关系
多对多关系
一对一关系
(2)Hibernate的一对多配置
1)搭建Hibernate基本环境
2)创建表
3) 创建实体
一的一方:放的是多的一方的集合
多的一方:放的是一的一方的对象
4) 创建映射
一的一方:配置的<set>集合
多的一方:配置<many-to-one>
5) 编写测试类
(3)Hibernate的一对多的操作
1) 级联操作:cascade,用于操作其关联的对象。
级联保存或更新
级联删除
2)测试对象导航
3)放弃外键维护权:inverse,用户控制是否有外键维护能力
2.Hibernate的多对多
(1)Hibernate的多对多配置
1)搭建Hibernate环境
2)创建表
3)创建实体:放置的是对方的集合
4)创建映射:配置的是对象的<set>
4)编写测试类
(2)Hibernate的多对多操作
1)级联操作
级联保存或更新
级联删除(了解)
2)其他的操作
给用户选择角色
给用户改选角色
给用户删除角色
客户与联系人,一个客户可以拥有多个联系人,但是一个联系人只能有一个客户
客户cst_customer为一的一方,联系人cst_linkman为多的一方
CREATE TABLE `cst_customer` ( `cust_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '客户编号(主键)', `cust_name` varchar(32) NOT NULL COMMENT '客户名称(公司名称)', `cust_source` varchar(32) DEFAULT NULL COMMENT '客户信息来源', `cust_industry` varchar(32) DEFAULT NULL COMMENT '客户所属行业', `cust_level` varchar(32) DEFAULT NULL COMMENT '客户级别', `cust_phone` varchar(64) DEFAULT NULL COMMENT '固定电话', `cust_mobile` varchar(16) DEFAULT NULL COMMENT '移动电话', PRIMARY KEY (`cust_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; CREATE TABLE `cst_linkman` ( `lkm_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '联系人编号(主键)', `lkm_name` varchar(16) DEFAULT NULL COMMENT '联系人姓名', `lkm_cust_id` bigint(32) DEFAULT NULL COMMENT '客户id', `lkm_gender` char(1) DEFAULT NULL COMMENT '联系人性别', `lkm_phone` varchar(16) DEFAULT NULL COMMENT '联系人办公电话', `lkm_mobile` varchar(16) DEFAULT NULL COMMENT '联系人手机', `lkm_email` varchar(64) DEFAULT NULL COMMENT '联系人邮箱', `lkm_qq` varchar(16) DEFAULT NULL COMMENT '联系人qq', `lkm_position` varchar(16) DEFAULT NULL COMMENT '联系人职位', `lkm_memo` varchar(512) DEFAULT NULL COMMENT '联系人备注', PRIMARY KEY (`lkm_id`), KEY `FK_cst_linkman_lkm_cust_id` (`lkm_cust_id`), CONSTRAINT `FK_cst_linkman_lkm_cust_id` FOREIGN KEY (`lkm_cust_id`) REFERENCES `cst_customer` (`cust_id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
这里的话多的一方的外键不是使用lik_cust_id表示,而是直接使用客户的对象来表示,因为对象的id就是多的一方的外键
(1)多的一方的映射的创建
(2)一的一方的映射的创建
hibernate.cfg.xml
package com.itheima.hibernate.utils; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; /** * Hibernate * @author jt * */ public class HibernateUtils { public static final Configuration cfg; public static final SessionFactory sf; static{ cfg = new Configuration().configure(); sf = cfg.buildSessionFactory(); } public static Session openSession(){ return sf.openSession(); } public static Session getCurrentSession(){ return sf.getCurrentSession(); } }
package com.itheima.hibernate.demo1; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import com.itheima.hibernate.domain.Customer; import com.itheima.hibernate.domain.LinkMan; import com.itheima.hibernate.utils.HibernateUtils; /** * 一对多的测试类 * @author jt * */ public class HibernateDemo1 { @Test // 保存2个客户 和 3个联系人 并且建立好关系 public void demo1(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 创建两个客户 Customer customer1 = new Customer(); customer1.setCust_name("王东"); Customer customer2 = new Customer(); customer2.setCust_name("赵洪"); // 创建三个联系人 LinkMan linkMan1 = new LinkMan(); linkMan1.setLkm_name("凤姐"); LinkMan linkMan2 = new LinkMan(); linkMan2.setLkm_name("如花"); LinkMan linkMan3 = new LinkMan(); linkMan3.setLkm_name("旺财"); // 设置关系: linkMan1.setCustomer(customer1); linkMan2.setCustomer(customer1); linkMan3.setCustomer(customer2); customer1.getLinkMans().add(linkMan1); customer1.getLinkMans().add(linkMan2); customer2.getLinkMans().add(linkMan3); // 保存数据: session.save(linkMan1); session.save(linkMan2); session.save(linkMan3); session.save(customer1); session.save(customer2); tx.commit(); }
一对多只保存一边可以吗?
(例如我们在将想要将一个客户进行删除,那么联动的就需要删除与这个客户相关的联系人,如果我们将联系人和客户用原始的方式进行删除,代码量将会很多。级联相当于我们删除客户会连同其联系人一起删除,反之亦然)
这里我们看到我们只需要保存customer那么与其关联的linkMan也会被保存。
这里发送四条的原因是linkMan1关联了customer,而customer关联了linkMan2和linkMan3,所以一共发了四条
发送三条是因为customer关联了linkMan2和linkMan3,而没有关联linkMan1
linkMan2没有与另外三个关联,所以只发送了一条
删除联系人级联删除客户(基本不用)
用户表
CREATE TABLE `sys_user` ( `user_id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '用户id', `user_code` varchar(32) NOT NULL COMMENT '用户账号', `user_name` varchar(64) NOT NULL COMMENT '用户名称', `user_password` varchar(32) NOT NULL COMMENT '用户密码', `user_state` char(1) NOT NULL COMMENT '1:正常,0:暂停', PRIMARY KEY (`user_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
角色表
CREATE TABLE `sys_role` ( `role_id` bigint(32) NOT NULL AUTO_INCREMENT, `role_name` varchar(32) NOT NULL COMMENT '角色名称', `role_memo` varchar(128) DEFAULT NULL COMMENT '备注', PRIMARY KEY (`role_id`) ) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
中间表(同为主键和外键)
CREATE TABLE `sys_user_role` ( `role_id` bigint(32) NOT NULL COMMENT '角色id', `user_id` bigint(32) NOT NULL COMMENT '用户id', PRIMARY KEY (`role_id`,`user_id`), KEY `FK_user_role_user_id` (`user_id`), CONSTRAINT `FK_user_role_role_id` FOREIGN KEY (`role_id`) REFERENCES `sys_role` (`role_id`) ON DELETE NO ACTION ON UPDATE NO ACTION, CONSTRAINT `FK_user_role_user_id` FOREIGN KEY (`user_id`) REFERENCES `sys_user` (`user_id`) ON DELETE NO ACTION ON UPDATE NO ACTION ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
用户映射
角色映射
package com.itheima.hibernate.demo2; import org.hibernate.Session; import org.hibernate.Transaction; import org.junit.Test; import com.itheima.hibernate.domain.Role; import com.itheima.hibernate.domain.User; import com.itheima.hibernate.utils.HibernateUtils; /** * Hibernate的多对多的映射 * @author jt * */ public class HibernateDemo2 { @Test /** * 保存多条记录:保存多个用户和角色 */ public void demo1(){ Session session = HibernateUtils.getCurrentSession(); Transaction tx = session.beginTransaction(); // 创建2个用户 User user1 = new User(); user1.setUser_name("赵洪"); User user2 = new User(); user2.setUser_name("李兵"); // 创建3个角色 Role role1 = new Role(); role1.setRole_name("研发部"); Role role2 = new Role(); role2.setRole_name("市场部"); Role role3 = new Role(); role3.setRole_name("公关部"); // 设置双向的关联关系: user1.getRoles().add(role1); user1.getRoles().add(role2); user2.getRoles().add(role2); user2.getRoles().add(role3); role1.getUsers().add(user1); role2.getUsers().add(user1); role2.getUsers().add(user2); role3.getUsers().add(user2); // 保存操作:多对多建立了双向的关系必须有一方放弃外键维护。 // 一般是被动方放弃外键维护权。 session.save(user1); session.save(user2); session.save(role1); session.save(role2); session.save(role3); tx.commit(); }
不可以只保存一边
1.保存用户级联保存角色
2.保存角色级联保存用户
1.删除用户级联删除角色
2.删除角色级联删除用户
1.给用户选择角色
2.给用户改选角色
3.给用户删除角色