关联关系映射:

  关联关系,是使用最多的一种关系,非常重要。在内存中反映为实体关系,映射到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--关联关系映射的更多相关文章

  1. Hibernate(6)—— 一对多 和 多对多关联关系映射(xml和注解)总结

    俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及的知识点总结如下: One to Many 映射关系 多对一单向外键关联(XML/Annotation) 一对多单向外键关联(XM ...

  2. Hibernate学习笔记-Hibernate关系映射

    1. 初识Hibernate——关系映射 http://blog.csdn.net/laner0515/article/details/12905711 2. Hibernate 笔记8 关系映射1( ...

  3. Hibernate—— 一对多 和 多对多关联关系映射(xml和注解)总结(转载)

    One to Many 映射关系 多对一单向外键关联(XML/Annotation) 一对多单向外键关联(XML/Annotation) 懒加载和积极加载 一对多双向外键关联(XML/Annotati ...

  4. Hibernate 实体关联关系映射【转】

    Hibernate关联关系映射目录│ ├─单向关联│  ├─  一对一外键单向关联│  ├─  一对一主键单向关联│  ├─  一对一连接表单向关联│  ├─  一对多外键单向关联│  ├─  一对多 ...

  5. Hibernate关联关系映射

    1.  Hibernate关联关系映射 1.1.  one to one <class name="Person"> <id name="id" ...

  6. Hibernate 实体关联关系映射----总结

    在我看来,Hibernate提供这些映射关系,常用就是一对一和多对一,并且在能不用连接表的时候尽量不要用连接表.多对多会用到,如果用到了,应该首先考虑底层数据库设计是否合理.   在实际开发中,在Hi ...

  7. Hibernate之关联关系映射(一对一主键映射和一对一外键映射)

    1:Hibernate的关联关系映射的一对一外键映射: 1.1:第一首先引包,省略 1.2:第二创建实体类: 这里使用用户信息和身份证信息的关系,用户的主键编号既可以做身份证信息的主键又可以做身份证信 ...

  8. SSH:Hibernate框架(七种关联关系映射及配置详解)

    概念 基本映射是对一个实体进行映射,关联映射就是处理多个实体之间的关系,将关联关系映射到数据库中,所谓的关联关系在对象模型中有一个或多个引用. 分类 关联关系分为上述七种,但是由于相互之间有各种关系, ...

  9. JPA(六):映射关联关系------映射单向一对多的关联关系

    映射单向一对多的关联关系 新建项目项目请参考<JPA(二):HellWord工程>,基于上一章讲解的<JPA(五):映射关联关系------映射单向多对一的关联关系>中的例子进 ...

随机推荐

  1. 如何修改antd中表格的表头样式和奇偶行颜色交替

    在做antd表格时通常会用到table组件,但是table的表头时给定的,那么怎么修改表头的颜色呢? 这里用的时less的写法,在全局环境中写,所有的table表头都会变成自己定义的颜色 定义好表头的 ...

  2. iphonex适配

    这一篇具体适配步骤比较全面 iphonex适配 这一篇图文讲解比较全面 关于H5页面在iPhoneX适配

  3. BZOJ2806_Cheat

    Ctsc2012的题目.做完感觉自己瞬间变高富帅了. 不过回想其实也觉得不难,想到用单调队列就很简单了,还有二分= =.呵 对于给出的一篇文章,如果你们将它分成若干段,并在所有长度不小于L的片段在字典 ...

  4. [UVALive 3902] Network

    图片加载可能有点慢,请跳过题面先看题解,谢谢 一道简单的贪心题,而且根节点已经给你了(\(S\)),这就很好做了. 显然,深度小于等于 \(k\) 的都不用管了(\(S\) 深度为0),那么我们只需要 ...

  5. NetApp常用巡检命令

    常用检查命令 environment status 查看环境信息 version 查看OS版本 sysconfig -v 查看系统信息(设备序列号 系统软.硬件信息等) sysconfig -a 查看 ...

  6. 【DSU on tree】【CF741D】Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths

    Description 给定一棵 \(n\) 个节点的树,每条边上有一个字符,字符集大小 \(22\),求每个节点的子树内最长的简单路径使得路径上的字符经过重排后构成回文串. Limitation \ ...

  7. 十、Shell基础

    一.shell概述 1.Shell是什么 shell是一个命令行解释器,他为用户提供了一个向linux内核发送请求以便运行程序的界面系统级程序,用户可以用shell来启动.挂起.停止甚至编写一些程序 ...

  8. 什么是Docker并且它为什么这么受欢迎

    什么是Docker (why it's so hot than hot) Docker是一个使用容器来方便快捷的创建,部署,运行程序的工具,容器允许开发人员将应用程序的一切打包(镜像),例如库和其他的 ...

  9. 安装VisualSVN Server 报错The specified TCP port is occupied

    安装过程中报错,如下图所示. The specified TCP port is occupied by another service.Please stop that service or use ...

  10. bayer, yuv, RGB转换方法

    因为我的STVxxx USB camera输出格式是bayer格式,手头上只有YUVTOOLS这个查看工具,没法验证STVxxx在开发板上是否正常工作. 网上找了很久也没找到格式转换工具,最后放弃了, ...