Hibernate5笔记5--关联关系映射
关联关系映射:
关联关系,是使用最多的一种关系,非常重要。在内存中反映为实体关系,映射到DB中为主外键关系。实体间的关联,即对外键的维护。关联关系的发生,即对外键数据的改变。
外键:外面的主键,即,使用其它表的主键值作为自已的某字段的取值。
(1) 基本概念:
关联属性:Java代码的实体类定义中,声明的另一个实例类类型或其集合类型的属性,称为关联属性。
关联关系维护:关联关系的维护,也称为外键维护,即为外键字段赋值。Hibernate默认情况下,关联的双方都具有维护权。即在代码中均可通过调用自己关联属性的set方法来建立关联关系。反映到数据库中,即是为外键字段赋值。
不过,由于外键是建立在多方表中的,所以对于外键的维护方式,即为外键字段赋值的方式,一方维护与多方维护,其底层执行是不同的。
若关联关系由一方维护,只能通过update语句来完成。若关联关系由多方维护,通过insert语句来完成。
虽然双方均具有维护权,但一方同时具有放弃维护权的能力。通过对一方关联属性inverse=“true”设置,即可放弃关联关系维护权,将维护权完全交给多方。
预处理语句:所谓预处理语句,即当前先不执行,等后面条件成熟,或程序运行完毕再执行的语句。
当一方具有关联关系的维护权,并且执行save(一方对象)时,会产生一条update预处理语句,用于维护外键值。当多方具有关联关系的维护权,并且执行save(多方对象)时,会产生一条insert预处理语句,用于维护外键值。
级联关系:当对某一类的对象a进行操作,如增加、删除、修改时,同时会自动对另一类的某对象b进行相同的操作。此时称,对象a、b具有级联关系,对象b为对象a的级联对象。
级联操作是通过映射文件的cascade属性设置的。该属性的值较多,其介绍如下:
none:在保存、更新或删除当前对象时,忽略其他关联的对象,即不使用级联。它是默认值。
save-update:当通过Session的save()、update()、saveOrUpdate()方法来保存或更新当前对象时,将级联到其他DB中的相关联的表。
delete:当通过Session的delete()方法删除当前对象时,将级联删除所有关联的对象。
all:包含save-update及delete级联的所有行为。另外,当对当前对象执行lock()操作时,也会对所有关联的持久化对象执行lock()操作。
delete-orphan:删除所有和当前对象解除关联关系的对象。
all-delete-orphan:包含all和delete-orphan级联的所有行为。
关联方向:(1)单向关联:指具有关联关系的实体对象间的加载与访问关系是单向的。即,只有一个实体对象可以加载和访问对方,但对方是看不到另一方的。
(2)双向关联 :指具有关联关系的实体对象间的加载与访问关系是双向的。即,任何一方均可加载和访问另一方。
关联数量:实体对象间的关系,从数量上可以划分为:1:1,1:n,n:1,m:n
总结底层执行:一对多关系中,一方维护关联关系,先插入多方数据,后插入一方数据,最后update多方表中的外键值(???是否正确);多方维护关联关系,先插入一方数据,后插入多方数据,在插入多方数据的同时插入外键值;
多对多关系中,哪一方维护关联关系,就是哪一方数据先插入,再插入关联方数据,最后插入中间表数据。
(2) 1:n单向关联(由一方维护关联关系):
一方实体类代码:
package com.tongji.beans; import java.util.HashSet;
import java.util.Set; public class Country {
private Integer cid;
private String cname;
private Set<Minister> ministers; //关联属性 public Country() {
super();
ministers = new HashSet<Minister>();
} public Country(String cname) {
this();
this.cname = cname;
} public Integer getCid() {
return cid;
} public void setCid(Integer cid) {
this.cid = cid;
} public String getCname() {
return cname;
} public void setCname(String cname) {
this.cname = cname;
} public Set<Minister> getMinisters() {
return ministers;
} public void setMinisters(Set<Minister> ministers) {
this.ministers = ministers;
} @Override
public String toString() {
return "Country [cid=" + cid + ", cname=" + cname + ", ministers=" + ministers + "]";
} }
一方映射文件代码:
<?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 package="com.tongji.beans">
<class name="Country">
<id name="cid">
<generator class="native"/>
</id>
<property name="cname"/>
<!-- 对关联属性的映射,inverse=true,表示一方放弃关联关系的维护权,这个不应该这么设置,只是为了演示错误 -->
<set name="ministers" cascade="save-update" inverse="true">
<key column="countryId"/>
<one-to-many class="Minister"/>
</set>
</class>
</hibernate-mapping>
其中,column是外键的名称
测试代码:
@Test
public void test03() {
//1. 获取Session
Session session = HbnUtils.getSession();
try {
//2. 开启事务
session.beginTransaction();
//3. 操作
Minister minsiter1 = new Minister("aaa");
Minister minsiter2 = new Minister("bbb");
Minister minsiter3 = new Minister("ccc"); Country country = new Country("USA");
//关联的建立在这里完成
country.getMinisters().add(minsiter1);
country.getMinisters().add(minsiter2);
country.getMinisters().add(minsiter3); session.save(country);
//4. 事务提交
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
//5. 事务回滚
session.getTransaction().rollback();
}
}
(2) 1:n双向关联:
一方实体类代码和一方映射文件代码同上;
多方实体类代码:
package com.tongji.beans; public class Minister {
private Integer mid;
private String mname;
private Country country; //关联属性 public Minister() {
super();
} public Minister(String mname) {
super();
this.mname = mname;
} public Integer getMid() {
return mid;
} public void setMid(Integer mid) {
this.mid = mid;
} public String getMname() {
return mname;
} public void setMname(String mname) {
this.mname = mname;
} public Country getCountry() {
return country;
} public void setCountry(Country country) {
this.country = country;
} @Override
public String toString() {
return "Minister [mid=" + mid + ", mname=" + mname + "]";
} }
多方映射文件代码:
<?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 package="com.tongji.beans">
<class name="Minister">
<id name="mid">
<generator class="native"/>
</id>
<property name="mname"/>
<!-- 关联属性名 -->
<many-to-one name="country" cascade="save-update"
class="Country" column="countryId"/>
</class>
</hibernate-mapping>
测试代码:
package com.tongji.test; import org.hibernate.Session;
import org.junit.Test; import com.tongji.beans.Country;
import com.tongji.beans.Minister;
import com.tongji.utils.HbnUtils; public class MyTest {
@Test
public void test00() {
//1. 获取Session
Session session = HbnUtils.getSession();
try {
//2. 开启事务
session.beginTransaction();
//3. 操作
Minister minister = new Minister("aaa"); Country country = new Country("USA");
//Country方在维护关联关系
country.getMinisters().add(minister); session.save(country);
//4. 事务提交
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
//5. 事务回滚
session.getTransaction().rollback();
}
} @Test
public void test01() {
//1. 获取Session
Session session = HbnUtils.getSession();
try {
//2. 开启事务
session.beginTransaction();
//3. 操作
Minister minister = new Minister("aaa"); Country country = new Country("USA");
//Minister方在维护关联关系
minister.setCountry(country); //谁在维护关联关系,就save()谁
session.save(minister);
//4. 事务提交
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
//5. 事务回滚
session.getTransaction().rollback();
}
}
}
(3) 自关联:
实体类代码:
package com.tongji.beans; import java.util.HashSet;
import java.util.Set; //新闻栏目
public class NewsLabel {
private Integer id;
private String name; //栏目名称
private String content; //栏目内容
private NewsLabel parentNewsLabel; //父栏目
private Set<NewsLabel> childNewsLabels; //子栏目 public NewsLabel() {
childNewsLabels = new HashSet<NewsLabel>();
} public NewsLabel(String name, String content) {
this();
this.name = name;
this.content = content;
} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getContent() {
return content;
} public void setContent(String content) {
this.content = content;
} public NewsLabel getParentNewsLabel() {
return parentNewsLabel;
} public void setParentNewsLabel(NewsLabel parentNewsLabel) {
this.parentNewsLabel = parentNewsLabel;
} public Set<NewsLabel> getChildNewsLabels() {
return childNewsLabels;
} public void setChildNewsLabels(Set<NewsLabel> childNewsLabels) {
this.childNewsLabels = childNewsLabels;
} @Override
public String toString() {
return "NewsLabel [id=" + id + ", name=" + name + ", content=" + content + "]";
} }
映射文件代码:
<?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 package="com.tongji.beans">
<class name="NewsLabel">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="content"/>
<!-- 站在一方角度 -->
<set name="childNewsLabels" cascade="save-update">
<key column="pid"/>
<one-to-many class="NewsLabel"/>
</set>
<!-- 站在多方角度 -->
<many-to-one name="parentNewsLabel" cascade="save-update"
class="NewsLabel" column="pid"/>
</class>
</hibernate-mapping>
测试代码:
package com.tongji.test; import org.hibernate.Session;
import org.junit.Test; import com.tongji.beans.NewsLabel;
import com.tongji.utils.HbnUtils; public class MyTest {
//让父方栏目维护关联关系,即一方维护
@Test
public void test00() {
//1. 获取Session
Session session = HbnUtils.getSession();
try {
//2. 开启事务
session.beginTransaction();
//3. 操作
NewsLabel footballNews = new NewsLabel("足球新闻","国足国足国足国足");
NewsLabel basketballNews = new NewsLabel("篮球新闻","登哥登哥登哥登哥"); NewsLabel sportsNews = new NewsLabel("体育新闻","奥运奥运奥运奥运"); sportsNews.getChildNewsLabels().add(footballNews);
sportsNews.getChildNewsLabels().add(basketballNews); session.save(sportsNews); //4. 事务提交
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
//5. 事务回滚
session.getTransaction().rollback();
}
} //让子方栏目维护关联关系,即多方维护
@Test
public void test01() {
//1. 获取Session
Session session = HbnUtils.getSession();
try {
//2. 开启事务
session.beginTransaction();
//3. 操作
NewsLabel basketballNews = new NewsLabel("篮球新闻","登哥登哥登哥登哥"); NewsLabel sportsNews = new NewsLabel("体育新闻","奥运奥运奥运奥运"); basketballNews.setParentNewsLabel(sportsNews); session.save(basketballNews); //4. 事务提交
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
//5. 事务回滚
session.getTransaction().rollback();
}
}
}
(4) n:1单向关联(由多方来维护关联关系):
一方实体类代码和一方映射文件代码为原来不考虑关联时候的样子,多方实体类代码和多方映射文件代码同(3)1:n双向关联,测试代码同(3)1:n双向关联的多方维护部分。
(5)n:m单向关联:
维护关联关系的一方的实体类代码:
package com.tongji.beans; import java.util.HashSet;
import java.util.Set; public class Student {
private Integer sid;
private String sname;
private Set<Course> courses; public Student() {
courses = new HashSet<Course>();
} public Student(String sname) {
this();
this.sname = sname;
} public Integer getSid() {
return sid;
} public void setSid(Integer sid) {
this.sid = sid;
} public String getSname() {
return sname;
} public void setSname(String sname) {
this.sname = sname;
} public Set<Course> getCourses() {
return courses;
} public void setCourses(Set<Course> courses) {
this.courses = courses;
} @Override
public String toString() {
return "Student [sid=" + sid + ", sname=" + sname + "]";
} }
维护关联关系的一方的映射文件代码:
<?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 package="com.tongji.beans">
<class name="Student">
<id name="sid">
<generator class="native"/>
</id>
<property name="sname"/>
<!-- 关联属性的映射 -->
<set name="courses" cascade="save-update" table="middle"> <!-- table指定多对多关系的中间表 -->
<key column="studentId"/> <!-- 指定当前类在中间表中对应的外键 -->
<many-to-many class="Course" column="courseId"/> <!-- 指定关联类在中间表中对应的外键 -->
</set>
</class>
</hibernate-mapping>
测试代码:
package com.tongji.test; import org.hibernate.Session;
import org.junit.Test; import com.tongji.beans.Course;
import com.tongji.beans.Student;
import com.tongji.utils.HbnUtils; public class MyTest {
//第一种解决方案
@Test
public void test00() {
//1. 获取Session
Session session = HbnUtils.getSession();
try {
//2. 开启事务
session.beginTransaction();
//3. 操作
Course course1 = new Course("Struts2");
Course course2 = new Course("Hibernate5");
Course course3 = new Course("Sring4"); Student student1 = new Student("张三");
Student student2 = new Student("李四"); student1.getCourses().add(course1);
student1.getCourses().add(course2); student2.getCourses().add(course1);
student2.getCourses().add(course3); session.save(student1);
session.save(student2);
//4. 事务提交
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
//5. 事务回滚
session.getTransaction().rollback();
}
} }
(6)n:m双向关联:
上述另一方实体类代码:
package com.tongji.beans; import java.util.HashSet;
import java.util.Set; public class Course {
private Integer cid;
private String cname;
private Set<Student> students; public Course() {
students = new HashSet<Student>();
} public Course(String cname) {
this();
this.cname = cname;
} public Integer getCid() {
return cid;
} public void setCid(Integer cid) {
this.cid = cid;
} public String getCname() {
return cname;
} public void setCname(String cname) {
this.cname = cname;
} public Set<Student> getStudents() {
return students;
} public void setStudents(Set<Student> students) {
this.students = students;
} @Override
public String toString() {
return "Course [cid=" + cid + ", cname=" + cname + "]";
} }
上述另一方映射文件代码:
<?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 package="com.tongji.beans">
<class name="Course">
<id name="cid">
<generator class="native"/>
</id>
<property name="cname"/>
<!-- 关联属性映射-->
<set name="students" cascade="save-update" table="middle">
<key column="courseId"/>
<many-to-many class="Student" column="studentId"/>
</set>
</class>
</hibernate-mapping>
测试代码:
package com.tongji.test; import org.hibernate.Session;
import org.junit.Test; import com.tongji.beans.Course;
import com.tongji.beans.Student;
import com.tongji.utils.HbnUtils; public class MyTest {
@Test
public void test00() {
//1. 获取Session
Session session = HbnUtils.getSession();
try {
//2. 开启事务
session.beginTransaction();
//3. 操作
Course course1 = new Course("Struts2");
Course course2 = new Course("Hibernate5");
Course course3 = new Course("Sring4"); Student student1 = new Student("张三");
Student student2 = new Student("李四"); student1.getCourses().add(course1);
student1.getCourses().add(course2); student2.getCourses().add(course1);
student2.getCourses().add(course3); session.save(student1);
session.save(student2);
//4. 事务提交
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
//5. 事务回滚
session.getTransaction().rollback();
}
} @Test
public void test01() {
//1. 获取Session
Session session = HbnUtils.getSession();
try {
//2. 开启事务
session.beginTransaction();
//3. 操作
Course course1 = new Course("Struts2");
Course course2 = new Course("Hibernate5");
Course course3 = new Course("Sring4"); Student student1 = new Student("张三");
Student student2 = new Student("李四"); course1.getStudents().add(student1);
course1.getStudents().add(student2); course2.getStudents().add(student2); course3.getStudents().add(student1); session.save(course1);
session.save(course2);
session.save(course3);
//4. 事务提交
session.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
//5. 事务回滚
session.getTransaction().rollback();
}
} }
Hibernate5笔记5--关联关系映射的更多相关文章
- Hibernate(6)—— 一对多 和 多对多关联关系映射(xml和注解)总结
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: One to Many 映射关系 多对一单向外键关联(XML/Annotation) 一对多单向外键关联(XM ...
- Hibernate学习笔记-Hibernate关系映射
1. 初识Hibernate——关系映射 http://blog.csdn.net/laner0515/article/details/12905711 2. Hibernate 笔记8 关系映射1( ...
- Hibernate—— 一对多 和 多对多关联关系映射(xml和注解)总结(转载)
One to Many 映射关系 多对一单向外键关联(XML/Annotation) 一对多单向外键关联(XML/Annotation) 懒加载和积极加载 一对多双向外键关联(XML/Annotati ...
- Hibernate 实体关联关系映射【转】
Hibernate关联关系映射目录│ ├─单向关联│ ├─ 一对一外键单向关联│ ├─ 一对一主键单向关联│ ├─ 一对一连接表单向关联│ ├─ 一对多外键单向关联│ ├─ 一对多 ...
- Hibernate关联关系映射
1. Hibernate关联关系映射 1.1. one to one <class name="Person"> <id name="id" ...
- Hibernate 实体关联关系映射----总结
在我看来,Hibernate提供这些映射关系,常用就是一对一和多对一,并且在能不用连接表的时候尽量不要用连接表.多对多会用到,如果用到了,应该首先考虑底层数据库设计是否合理. 在实际开发中,在Hi ...
- Hibernate之关联关系映射(一对一主键映射和一对一外键映射)
1:Hibernate的关联关系映射的一对一外键映射: 1.1:第一首先引包,省略 1.2:第二创建实体类: 这里使用用户信息和身份证信息的关系,用户的主键编号既可以做身份证信息的主键又可以做身份证信 ...
- SSH:Hibernate框架(七种关联关系映射及配置详解)
概念 基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用. 分类 关联关系分为上述七种,但是由于相互之间有各种关系, ...
- JPA(六):映射关联关系------映射单向一对多的关联关系
映射单向一对多的关联关系 新建项目项目请参考<JPA(二):HellWord工程>,基于上一章讲解的<JPA(五):映射关联关系------映射单向多对一的关联关系>中的例子进 ...
随机推荐
- 谁能告诉delphi7 的updatebatch使用属性说明?
谁能告诉delphi7 的updatebatch使用属性说明? ADODataSet1.UpdateBatch(arAll); 就是提交你的数据集到数据库 arCurrentOnly the upda ...
- libuv 简单使用
libuv 简单使用 来源:https://zhuanlan.zhihu.com/p/50497450 前序:说说为啥要研究libuv,其实在很久之前(大概2年前吧)玩nodejs的时候就对这个核心库 ...
- 【BZOJ4006】管道连接(动态规划,斯坦纳树)
题面 BZOJ 洛谷 题解 和这题区别不是很大吧. 基本上拿过来改一下就做完了. #include<iostream> #include<cstdio> #include< ...
- 【BZOJ1034】泡泡堂(贪心)
[BZOJ1034]泡泡堂(贪心) 题面 BZOJ 洛谷 题解 很基础的贪心,然而我竟然没写对...身败名裂. 大概就是类似田忌赛马. 先拿看当前最大值是否能否解决对面最大值,否则检查能否用最小值来兑 ...
- 《Linux内核分析》期末总结及学习心得
[洪韶武 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.com/course/USTC-1000029000 ] 一.学习心得 本学 ...
- 正确理解 LEAL (Load Effective Address) 指令
LEAL: leal S, D -> D ← &S 在 CSAPP (Computer Systems: A Programmer’s Perspective) 中,对 LE ...
- golang简单实现二叉树的数据添加和遍历
代码实现 package tree import "fmt" type Node struct { elem interface{} left, right *Node } typ ...
- 实用 zsh 插件
zsh 命令补全插件 zsh-users/zsh-autosuggestions laravel5(使用前提:安装了 oh-my-zsh) 使用方法,修改 ~/.zshrc,在 plugins 里面加 ...
- bzoj 1798 线段树
1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MBSubmit: 7163 Solved: 2587[Submit ...
- PythonCodingRule简略