Hibernate_03
Hibernate_03
勤劳的开发者px 发表于3个月前
Hibernate_03
  • 发表于 3个月前
  • 阅读 1
  • 收藏 0
  • 点赞 0
  • 评论 0

一对多关系

概念

一对多关系是关系型数据库中两个表之间的一种关系。在ORM中,如何通过对象描述表之间的关系,是ORM核心。通常 在数据库层级中,两表之间是有主外键关系的。

数据库方式建立一对多模型

-- 用户表
CREATE TABLE t_user (
	u_id INT PRIMARY KEY AUTO_INCREMENT,
	u_name VARCHAR(255),
	u_age INT
);
-- 号码表
CREATE TABLE t_phone (
	p_id INT PRIMARY KEY AUTO_INCREMENT,
	p_number VARCHAR(255),
	fk_u_id INT
);
-- 用户表和电话表的主外键关系
ALTER TABLE t_phone
ADD CONSTRAINT fk_user_phone FOREIGN KEY(fk_u_id) REFERENCES t_user(u_id); 

代码生成一对多模型步骤

  1. 导入Hibernate框架的Jar
  2. 新建持久化类:  在多方持久类中无需新建外键属性
  3. 配置映射文件: 配置中无需为外键属性提供<property>标签
  4.           关系结构描述
  5. 配置hibernate启动文件
  6. 通过代码生成表结构

一方结构描述

持久化类中描述

在一方的持久化类中,通过set集合描述多方,将多方集合作为自己的属性存在。

private Set<Phone> phones = new HashSet<>();

映射文件描述

在一方的class标签中添加 标签

<set name="phones">
<!-- 外键列名,多方中 -->
<key column="u_id"/>
<one-to-many class="org.itheima.hibernate.domain.Phone" />
</set>
  • set标签中name属性: 持久化类中多方set集合的属性名称
  • key标签中的column属性: 外键名称。多方表中的外键列名,与一方表的主键构成主外键关系。
  • one-to-many标签: 代表当前是一方(一方)
  • one-to-many标签中的class: 指向多方的类名

多方结构描述

持久化类中描述

在多方的持久化类中,通过一方对象类型描述一方,将一方对象作为自己属性存在。

private User user;

映射文件描述

在多方的class标签中添加 标签

<many-to-one 
name="user" 
class="org.itheima.hibernate.domain.User" 
column="fk_u_id" />
  • 通过many-to-one标签标记当前是多方。
  • name属性: 多方持久类中一方的属性名称。
  • class属性: 多方持久类中一方的属性对应的类名。
  • column属性: 多方数据库表中的外键名称,此外键是关联一方数据库表的主键的。

级联操作的概念

  • 当对主对象进行某种操作时是否对其关联的从对象也作类似的操作
  • cascade的取值
    • none:不使用级联
    • save-update:级联保存或更新
    • delete:级联删除
    • delete-orphan:孤儿删除.(注意:只能应用在一对多关系)
    • all:除了delete-orphan的所有情况.(包含save-update delete)
    • all-delete-orphan:包含了delete-orphan的所有情况.(包含save-update delete delete-orphan)

一方的级联操作

级联保存和修改

在一方的映射文件中set标签中配置cascade属性为save-update

<set name="phones" cascade="save-update">
	<!-- 外键列名,多方中 -->
	<key column="fk_u_id"/>
	<one-to-many class="org.itheima.hibernate.domain.Phone" />
</set>

级联保存针对的是,如果数据操作保存一方的数据时,对多方数据库造成的影响。

//创建一方持久化对象
User user = new User();
user.setName("张三");
user.setAge(10);
session.save(user);
// 创建多方持久化对象
Phone p1 = new Phone();
p1.setP_number("13512345678");
// 建立一方和多方的关系
user.getPhones().add(p1);

注意:

  • 不配置级联保存和更新,非持久化状态的多方数据将无法保存成功,需要单独的去操作多方表。
  • 配置了级联保存和更新,非持久化状态的多方数据可以保存成功。

级联更新针对的是,如果数据操作为一方数据再次关联新的多方数据时,对多方数据库造成的影响。

//获得一方的持久化对象
User user = session.get(User.class, 1);
Set<Phone> phones = user.getPhones();
//创建多方的持久化对象
Phone phone = new Phone();
phone.setP_number("8888888");
//建立一方和多方的关系
phones.add(phone);

注意:

  • 不配置级联保存和更新,再次关联新的多方数据将无法保存到多方表中,需要单独的去操作多方表。
  • 配置了级联保存和更新,再次关联新的多方数据会自动保存到多方表中

级联删除

在一方的映射文件中set标签中配置cascade属性为delete

<set name="phones" cascade="delete">
	<!-- 外键列名,多方中 -->
	<key column="fk_u_id"/>
	<one-to-many class="org.itheima.hibernate.domain.Phone" />
</set>

级联删除针对的是 如果数据操作将一方的数据删除,对多方的数据造成的影响。

//user为一方表,phone为多方表,删除user时,对phone表造成怎样的影响
User user = session.get(User.class, 1);
session.delete(user);

注意:

  • 非级联删除只会删除一方数据库表中的记录,不会删除多方表中的记录,只是多方表中记录的外键设置为空
  • 级联删除既会删除一方数据库表中的记录,也会删除多方表中的记录
  • 开发过程中不会有任何删除操作

孤儿删除

在一方的映射文件中set标签中配置cascade属性为delete-orphan

<set name="phones" cascade="delete-orphan">
	<!-- 外键列名,多方中 -->
	<key column="fk_u_id"/>
	<one-to-many class="org.itheima.hibernate.domain.Phone" />
</set>

孤儿删除针对的是 一方和多方间关系解除时,对多方数据造成的影响

//user为一方表,phone为多方表,user和phone关系解除时,对phone表造成怎样的影响
User user = session.get(User.class, 1);
Phone phone = session.get(Phone.class, 1);
user.getPhones().remove(phone);

注意:

  • 非孤儿删除,不会删除多方数据,只会将多方表中的外键设置为空
  • 孤儿删除会删除多方数据库表中的记录
  • 开发过程中不会有任何删除操作

外键维护

概念

inverse:外键维护,默认为false。代表一方不去维护多方外键。(inverse有反转的意思)

  • true:一方不去维护多方外键操作
  • false: 一方去维护多方外键操作
  • 外键维护针对的是具有外键关联的主键表而言的

一方的放弃外键维护

<set name="phones" inverse="true">
	<!-- 外键列名,多方中 -->
	<key column="u_id"/>
	<one-to-many class="org.itheima.hibernate.domain.Phone" />
</set>

多方的级联操作

级联保存和修改

在多方的映射文件中many-to-one标签中配置cascade属性为save-update

<many-to-one 
	name="user" 
	class="org.itheima.hibernate.domain.User"
	column="u_id" 
	cascade="save-update" />

级联保存针对的是,如果数据操作保存多方的数据时,对一方数据库造成的影响。

//创建多方持久化对象
Phone phone = new Phone();			
phone.setP_number("13512345678");
//保存多方持久化对象
session.save(phone);
//创建一方持久化对象
User user = new User();
user.setName("张三疯");
user.setAge(100);
//建立关系
phone.setUser(user);

注意

  • 不配置级联保存和更新,非持久化状态的一方数据将无法保存成功,需要单独的去操作一方表。
  • 配置了级联保存和更新,非持久化状态的一方数据可以保存成功。

级联更新针对的是,如果数据操作为多方数据再次关联新的一方数据时,对一方数据库造成的影响。

//获得多方持久化对象
Phone phone = session.get(Phone.class, 1);
//创建新的一方持久化对象
User user = new User();
user.setName("张天宝");
user.setAge(10);
//建立关系
phone.setUser(user);

注意

  • 不配置级联保存和更新,再次关联新的一方数据将无法保存到一方表中,需要单独的去操作多方表。
  • 配置了级联保存和更新,再次关联新的一方数据会自动保存到一方表中

级联删除

在多方的映射文件中many-to-one标签中配置cascade属性为delete

<many-to-one 
	name="user" 
	class="org.itheima.hibernate.domain.User"
	column="u_id" 
	cascade="delete" />

注意:

  • 多方的级联删除并不是把一方的数据删除,清除的是自己的数据
  • 级联删除并不会删除多方数据库表中的记录,只是将此记录的外键设置为空
  • 开发过程中不会有任何删除操作

多对多的关系

概念

多对多关系是关系数据库中两个表之间的一种数据关系,为了维护这种关系,通常会存在一张中间关系表。两张表都只和关系表间建立主外键关系。

关键字:关系表,主外键关系

数据库方式建立多对多模型

-- 学生表
CREATE TABLE t_student (
	s_id INTEGER NOT NULL AUTO_INCREMENT,
	s_name VARCHAR(255),
	s_age VARCHAR(255),
	PRIMARY KEY (S_ID)
);
-- 教师表
CREATE TABLE t_teacher (
	t_id INTEGER NOT NULL AUTO_INCREMENT,
	t_name VARCHAR(255),
	t_age INTEGER,
	PRIMARY KEY (t_id)
);
-- 关系表
CREATE TABLE r_student_teacher (
	st_id INT PRIMARY KEY AUTO_INCREMENT,
	fk_s_id INTEGER,
	fk_t_id INTEGER
);
-- 教师表和关系表的主外键关系
ALTER TABLE r_student_teacher 
ADD CONSTRAINT fk_teacher FOREIGN KEY (fk_t_id) REFERENCES t_teacher (t_id);
-- 学生表和关系表的主外键关系
ALTER TABLE r_student_teacher 
ADD CONSTRAINT fk_student FOREIGN KEY (fk_s_id) REFERENCES t_student (s_id);

代码生成多对多模型步骤

  1. 导入Hibernate框架的Jar
  2. 新建表结构对应的持久化类:无需为中间关系表创建持久化类
  3. 配置映射文件
  4. 关系结构描述
  5. 配置hibernate启动文件
  6. 通过代码生成表结构

结构描述

持久化类中的描述

Student类中描述teachers

//通过set集合描述 多对多的关系
private Set<Teacher> teachers = new HashSet<>();

Teacher类中描述students

//通过set集合描述 多对多的关系
private Set<Student> students = new HashSet<>();

映射文件的描述

Student映射中描述teachers

<set name="teachers" table="r_student_teacher">
	<key column="fk_s_id" />
	<many-to-many class="org.itheima.hibernate.domain.Teacher"
		column="fk_t_id" />
</set>

Teacher映射中描述students

<set name="students" table="r_student_teacher">
	<key column="fk_t_id" />
	<many-to-many class="org.itheima.hibernate.domain.Student" 
		column="fk_s_id" />
</set>
  • set标签用来描述多的关系
  • set标签中name属性对应中类中描述多的关系的属性名称
  • set标签中table属性对应中多对多的中间关系表的表名
  • key标签是用来维护外键的
  • key标签中的column属性指的是当前对应的表的主键,在中间关系表中对应的外键的名称
  • many-to-many标签是用来描述多对多的关系
  • many-to-many标签中class属性指的是对应多的类的全名称。
  • many-to-many标签中column属性指的是对应多的表的主键,在中间关系表中对应的外键的名称

级联操作

级联保存和修改

在多方的映射文件中的set标签中配置cascade属性为save-update

<set name="teachers" table="r_student_teacher" cascade="save-update">
	<key column="fk_s_id" />
	<many-to-many class="org.itheima.hibernate.domain.Teacher"
				column="fk_t_id" />
</set>

级联保存针对的是,如果数据操作保存正向多方的数据时,对反向多方数据库造成的影响。

//创建正向多方持久化对象1
Student s1 = new Student();
s1.setS_name("张三");
s1.setS_age(18);
session.save(s1);
//创建正向多方持久化对象2
Student s2 = new Student();
s2.setS_name("李四");
s2.setS_age(28);
session.save(s2);
//创建反向多方持久化对象1
Teacher t1 = new Teacher();
t1.setT_name("王五");
t1.setT_age(70);
//创建反向多方持久化对象2
Teacher t2 = new Teacher();
t2.setT_name("赵六");
t2.setT_age(30);
// 建立关系
s1.getTeachers().add(t1);
s1.getTeachers().add(t2);
s2.getTeachers().add(t1);
s2.getTeachers().add(t2);

注意

  • 不配置级联保存和更新,非持久化状态的反向多方数据将无法保存成功,需要单独的去操作多方表。
  • 配置了级联保存和更新,非持久化状态的反向多方数据可以保存成功,保存到反向多方表和中间关系表中。

级联更新针对的是,如果数据操作为正向多方数据再次关联新的反向多方数据时,对反向多方数据库造成的影响。

//获得正向多方持久化对象
Student s = session.get(Student.class, 1);
//创建新的反向多方持久化对象
Teacher t = new Teacher();
t.setT_name("teacher");
t.setT_age(100);
//更新数据
s.getTeachers().add(t);

注意

  • 不配置级联保存和更新,再次关联新的反向多方数据将无法保存到正向多方表中,需要单独的去操作多方表。
  • 配置了级联保存和更新,再次关联新的反向多方数据会自动保存到反向多方表和中间关系表中

级联删除

在多方的映射文件中的set标签中配置cascade属性为delete

<set name="teachers" table="r_student_teacher" cascade="delete">
	<key column="fk_s_id" />
	<many-to-many class="org.itheima.hibernate.domain.Teacher"
				column="fk_t_id" />
</set>

级联删除针对的是 如果数据操作将正向多方表的数据删除,对反向多方表和中间关系表的数据造成的影响。

//获得正向多方的持久化对象
Student s = session.get(Student.class, 1);
session.delete(s);

注意

  • 非级联删除只会删除正向多方数据库表和中间关系表中的记录,不会删除反向多方表中的记录
  • 级联删除既会删除正向多方数据库表中的记录,也会删除反向多方表中的记录和中间关系表中的记录
  • 开发过程中不会有任何删除操作
共有 人打赏支持
粉丝 2
博文 47
码字总数 96234
评论 (0)
×
勤劳的开发者px
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: