hibernate_day03_MySQL数据库-表与表之间的多对多关系-实例
hibernate_day03_一对多相关操作
【1】一对多关系只保存一边是否可以 :不可以,会报错(瞬时对象异常)。
【2】一对多的级联操作 :
- 什么叫做级联
- 级联指的是,操作一个对象的时候,是否会同时操作其关联的对象。
- 级联是有方向性
- 操作一的一方的时候,是否操作到多的一方
- 操作多的一方的时候,是否操作到一的一方
【3】级联保存或更新 :
【4】测试对象的导航 :
【5】级联删除 :
【6】一对多设置了双向关联产生多余的SQL语句 :
【7】区分cascade和inverse :
(1)HibernateDemo1.java :
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;
/**
*
* * 一对多的测试类
* */
public class HibernateDemo1 {
// @Test
// // 保存2个客户 和 3个联系人 并且建立好关系
// public void demo1() {
// Session session = HibernateUtils.getCurrentSession();
// Transaction tx = session.beginTransaction();
//
// // 创建两个客户
// Customer customer1 = new Customer();
// customer1.setCust_name("wd");
// Customer customer2 = new Customer();
// customer2.setCust_name("zh");
//
// // 创建三个联系人
// LinkMan linkMan1 = new LinkMan();
// linkMan1.setLkm_name("fengjie");
// LinkMan linkMan2 = new LinkMan();
// linkMan2.setLkm_name("ruhua");
// LinkMan linkMan3 = new LinkMan();
// linkMan3.setLkm_name("wangcai");
//
// // 设置关系: 【一个客户 对应 多个联系人。】
// 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();
// }
//
// @Test
// // 一对多关系只保存一边[客户 or 联系人]是否可以:不可以[报错]
// public void demo2() {
// Session session = HibernateUtils.getCurrentSession();
// Transaction tx = session.beginTransaction();
//
// Customer customer = new Customer(); //瞬时
// customer.setCust_name("zhaohong");
//
// LinkMan linkMan = new LinkMan();
// linkMan.setLkm_name("ruhua");
//
// customer.getLinkMans().add(linkMan);// 客户关联联系人
// linkMan.setCustomer(customer); // 联系人关联客户
//
// // 只保存一边是否可以:
// // 不可以,报一个瞬时对象异常:持久态对象关联了一个瞬时态对象。
// //session.save(customer);
// session.save(linkMan);
//
// //通过级联操作,可解决 异常
//
// tx.commit();
// }
//
// @Test
// /**
// * 级联保存或更新操作: * 保存客户级联联系人,操作的主体是客户对象,需要在Customer.hbm.xml中进行配置 *
// * <set name="linkMans" cascade="save-update">
// * 【session.save(customer); 保存谁,配置谁 】
// */
// public void demo3() {
// Session session = HibernateUtils.getCurrentSession();
// Transaction tx = session.beginTransaction();
//
// Customer customer = new Customer();
// customer.setCust_name("zhaohong");
//
// LinkMan linkMan = new LinkMan();
// linkMan.setLkm_name("ruhua");
//
// customer.getLinkMans().add(linkMan);
// linkMan.setCustomer(customer);
//
// session.save(customer);
//
// tx.commit();
// }
//
// @Test
// /**
// * 级联保存或更新操作: * 保存联系人级联客户,操作的主体是联系人对象,需要在LinkMan.hbm.xml中进行配置 *
// * <many-to-one name="customer" cascade="save-update" class=
// * "com.itheima.hibernate.domain.Customer" column="lkm_cust_id"/>
// */
// public void demo4() {
// Session session = HibernateUtils.getCurrentSession();
// Transaction tx = session.beginTransaction();
//
// Customer customer = new Customer();
// customer.setCust_name("libing");
//
// LinkMan linkMan = new LinkMan();
// linkMan.setLkm_name("fengjie");
//
// customer.getLinkMans().add(linkMan);
// linkMan.setCustomer(customer);
//
// session.save(linkMan);
//
// tx.commit();
// }
// @Test
// /**
// * 测试对象的导航
// * * 前提:一对多的双方都设置cascade="save-update"
// */
// public void demo5() {
// Session session = HibernateUtils.getCurrentSession();
// Transaction tx = session.beginTransaction();
//
// Customer customer = new Customer();
// customer.setCust_name("libing");
//
// LinkMan linkMan1 = new LinkMan();
// linkMan1.setLkm_name("fengjie");
// LinkMan linkMan2 = new LinkMan();
// linkMan2.setLkm_name("ruhua");
// LinkMan linkMan3 = new LinkMan();
// linkMan3.setLkm_name("furong");
//
// // 凤姐找李冰,李冰找如花、芙蓉
// linkMan1.setCustomer(customer); // 1号联系人关联客户
// customer.getLinkMans().add(linkMan2); // 客户关联2号联系人
// customer.getLinkMans().add(linkMan3); // 客户关联3号联系人
//
// // 双方都设置了cascade
// session.save(linkMan1); // 发送几条insert语句 4条
// // [session.save(linkMan1);] linkMan1、[linkMan1.setCustomer(customer);] customer、
// // [customer.getLinkMans().add(linkMan2);]linkMan2、[customer.getLinkMans().add(linkMan3);]linkMan3 所以,4条语句
//
// //session.save(customer); // 发送几条insert语句 3条
// // customer.getLinkMans().add(linkMan2); \ customer.getLinkMans().add(linkMan3);
//
// //session.save(linkMan2); // 发送几条insert语句 1条
//
// tx.commit();
// }
//
// @Test
// /**
// * 级联删除:
// * * 删除客户级联删除联系人,删除的主体是客户,需要在Customer.hbm.xml中配置
// * * <set name="linkMans" cascade="delete">
// * * cascade="save-update,delete" :同时具有2个功能。
// */
// public void demo6(){
// Session session = HibernateUtils.getCurrentSession();
// Transaction tx = session.beginTransaction();
//
// // 没有设置级联删除,默认情况:修改了联系人的外键,删除客户
// /*Customer customer = session.get(Customer.class, 1l);
// session.delete(customer);*/
//
// // 删除客户,同时删除联系人
// Customer customer = session.get(Customer.class, 1l);
// session.delete(customer);
//
// tx.commit();
// }
//
// @Test
// /**
// * 级联删除:
// * * 删除联系人级联删除客户,删除的主体是联系人,需要在LinkMan.hbm.xml中配置
// * * <many-to-one name="customer" cascade="delete">
// */
// public void demo7(){
// Session session = HibernateUtils.getCurrentSession();
// Transaction tx = session.beginTransaction();
//
// // 删除客户,同时删除联系人
// /**
// * 先查询,再删除。
// * 不能直接创建对象去删除。创建对象,集合为空,无法删除。
// * get()后,查询客户关联的集合,有数据,可删除。
// */
// LinkMan linkMan = session.get(LinkMan.class, 3l);
// session.delete(linkMan);
//
// tx.commit();
// }
// @Test
// /**
// * 将2号联系人原来归1号客户,现在改为2号客户
// */
// public void demo8(){
// Session session = HibernateUtils.getCurrentSession();
// Transaction tx = session.beginTransaction();
//
// // 查询2号联系人
// LinkMan linkMan = session.get(LinkMan.class, 2l);//持久态对象
// // 查询2号客户
// Customer customer = session.get(Customer.class, 2l);//持久态对象
// // 双向的关联
// linkMan.setCustomer(customer);
// customer.getLinkMans().add(linkMan);
//
// //持久态对象发生变化,自动更新数据库
//
// tx.commit();
// }
@Test
/**
* 区分cascade和inverse的区别
*/
public void demo9(){
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
Customer customer = new Customer();
customer.setCust_name("libing");
LinkMan linkMan = new LinkMan();
linkMan.setLkm_name("fengjie");
customer.getLinkMans().add(linkMan);
// 条件在Customer.hbm.xml上的set中配置了cascade="save-update" inverse="true"
/**
* Customer.hbm.xml : <set name="linkMans" cascade="save-update" inverse="true">
* LinkMan.hbm.xml : <many-to-one name="customer" class="com.itheima.hibernate.domain.Customer" column="lkm_cust_id"/>
*/
session.save(customer); // 客户会插入到数据库,联系人也会插入到数据库,但是外键为null
/* cascade : 控制对象的关联对象。操作关联对象【客户进入数据库,客户关联的对象也会进入数据库】
* inverse="true" : 控制一的一方能不能维护外键。true放弃外键
*/
tx.commit();
}
}
(2)Customer.hbm.xml :
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入约束-配置约束 -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- name是Customer类的全路径 -->
<class name="com.itheima.hibernate.domain.Customer" table="cst_customer">
<!-- 建立OID与主键映射 -->
<id name="cust_id" column="cust_id">
<!-- 主键生成策略 -->
<generator class="native"/>
</id>
<!-- 建立普通属性与数据库表字段映射 -->
<property name="cust_name" column="cust_name" />
<property name="cust_source" column="cust_source"/>
<property name="cust_industry" column="cust_industry"/>
<property name="cust_level" column="cust_level"/>
<property name="cust_phone" column="cust_phone"/>
<property name="cust_mobile" column="cust_mobile"/>
<!-- 配置一对多的映射:放置的多的一方的集合 -->
<!-- set标签 :
* name :多的一方的对象集合的属性名称。[ Customer.java类 ]
* cascade:级联【save-update 保存或更新】
* inverse:放弃外键维护权true。
cascade="save-update,delete" 同时具有2个功能。
-->
<set name="linkMans" cascade="save-update" inverse="true">
<!-- key标签 : 【column :多的一方的外键的名称。】-->
<key column="lkm_cust_id"/>
<!-- one-to-many标签 : 【class : 多的一方的类的全路径。】-->
<one-to-many class="com.itheima.hibernate.domain.LinkMan"/>
</set>
</class>
</hibernate-mapping>
(3)LinkMan.hbm.xml :
<?xml version="1.0" encoding="UTF-8"?>
<!-- 引入约束-配置约束 -->
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<!-- name是Customer类的全路径 -->
<class name="com.itheima.hibernate.domain.LinkMan" table="cst_linkman">
<!-- 建立OID与主键映射 -->
<id name="lkm_id" column="lkm_id">
<!-- 主键生成策略 -->
<generator class="native"/>
</id>
<!-- 建立普通属性与表字段映射 ; name与column相等,column可省略-->
<property name="lkm_name"/>
<property name="lkm_gender"/>
<property name="lkm_phone"/>
<property name="lkm_mobile"/>
<property name="lkm_email"/>
<property name="lkm_qq"/>
<property name="lkm_position"/>
<property name="lkm_memo"/>
<!-- 【联系人:多】 配置多对一的关系:放置的是一的一方的对象 -->
<!-- 多对一
many-to-one标签
* name : 一的一方的对象的属性名称。【LinkMan.java类】
* class : 一的一方的类的全路径。
* column : 在多的一方的表的外键的名称。 -->
<many-to-one name="customer" class="com.itheima.hibernate.domain.Customer" column="lkm_cust_id"/>
</class>
</hibernate-mapping>
博主QQ : 386335886
代码来源 :bilibili网站(https://www.bilibili.com/video/av33127718?p=31)
夫心起于善,善虽未为,而吉神已随之。其有曾行恶事,后自改悔,诸恶莫作,众善奉行,久久必获吉庆,所谓转祸为福也。
故吉人语善、视善、行善,一日有三善,三年天必降之福。凶人语恶、视恶、行恶,一日有三恶,三年天必降之祸。胡不勉而行之?