1.双向 1-n 与 双向 n-1 是完全相同的两种情形,这里使用双向多对一来演示

双向 1-n 需要在 1 的一端可以访问 n 的一端, 反之依然.

出版社和图书的关系:Publishers——Books

2.实体类

n端

Books.java

public class Books {

    private Integer Id;
private String Title;
private String Author;
private String ISBN;
private int WordCount;
private double UnitPrice;
private String ContentDescription;
//实体类类型属性
private Publishers publisher;
//忽略getter和setter方法
...
}

1端

Publishers.java

public class Publishers {

    private Integer id;
private String Name;
//集合属性
private Set<Books> bks = new HashSet<>();
//忽略getter和setter方法
...
}

3.映射文件

n端:

<hibernate-mapping package="com.withXml.bothmanyToone.entity" auto-import="false">

    <class name="Books" table="BOTH_BOOKS">

        <id name="Id" type="java.lang.Integer" access="field">
<column name="ID" />
<generator class="native" />
</id> <property name="Title" type="java.lang.String">
<column name="TITLE" />
</property> <property name="Author" type="java.lang.String">
<column name="AUTHOR" />
</property> <property name="ISBN" type="java.lang.String">
<column name="ISBN" />
</property> <property name="WordCount" type="integer">
<column name="WORD_COUNT"/>
</property> <!-- 映射数据表字段你的类型,可以在property 里面使用type设置,也可以在column里面使用 sql-type-->
<property name="UnitPrice">
<column name="UNIT_PRICE" sql-type="double" />
</property> <property name="ContentDescription" type="java.lang.String">
<column name="CONTENT_DESCRIPTION" />
</property> <!-- 配置多对一关联映射 -->
<many-to-one name="publisher" class="Publishers"
column="PUBLISHER_ID" cascade="save-update"></many-to-one>
</class>
</hibernate-mapping>

1端

<hibernate-mapping package="com.withXml.bothmanyToone.entity" auto-import="false">

    <class name="Publishers" table="BOTH_PUBLISHERS">

        <id name="id" type="java.lang.Integer" access="field">
<column name="ID" />
<generator class="native" />
</id> <property name="Name" type="java.lang.String">
<column name="NAME" />
</property> <!--
cascade(级联)级联的意思是指两个对象之间的操作联运关系,对一个对象执行了操作之后,
对其指定的级联对象也需要执行相同的操作,取值:all,none,save_update,delete。
1.all:代码在所有情况下都执行级联操作
2.none:在所有情况下都不执行级联操作
3.save-update:在保存和更新的情况下执行级联操作
4.delete:在删除的时候执行级联操作
inverse:属性设置为true代表一的一方不在拥有关联关系的控制权,而把控制权交给多的一方
-->
<set name="bks" lazy="false" inverse="true" cascade="save-update,delete">
<!-- <key>指定PUBLISHERS数据表的外键,使用的是BOOKS表中的PUBLISHER_ID列 -->
<key column="PUBLISHER_ID"></key>
<one-to-many class="Books"/>
</set>
</class>
</hibernate-mapping>

4.CRUD测试

①保存

/**
* 保存操作,保存1的一端
*/
@Test
public void testBothManyToOneSave(){
//创建出版社对象
Publishers publisher = new Publishers();
publisher.setName("北京大学出版社"); //新建图书对象
Books book = new Books();
book.setTitle("大学英语");
book.setISBN("2018012103");
book.setAuthor("李玲");
book.setWordCount(10000);
book.setUnitPrice(95.5);
book.setContentDescription("无"); //新建图书对象
Books book2 = new Books();
book2.setTitle("管理学");
book2.setISBN("2018012104");
book2.setAuthor("张青");
book2.setWordCount(10000);
book2.setUnitPrice(95.5);
book2.setContentDescription("无"); //双向维护关系
//设置关联关系,指定一到多的关联关系 ,若由1端维护关系,会产生update语句,影响效率,
//所以在1端映射文件中设置inverse="true",控制权交给n端维护关系
publisher.getBks().add(book);
publisher.getBks().add(book2); //设置关联关系,指定多到一的关联关系
book.setPublisher(publisher);
book2.setPublisher(publisher); //执行保存,设置cascade级联属性之后,
//只保存一端即可(哪一端设置级联属性,可以只保存那一段,两端都设置,则任意一端都可以执行保存)
session.save(publisher);
}

②保存2

    /**
* 保存操作
*/
@Test
public void testBothManyToOneSave2(){
//创建出版社对象
Publishers publisher = new Publishers();
publisher.setName("北京大学出版社"); //新建图书对象
Books book = new Books();
book.setTitle("大学英语");
book.setISBN("2018012103");
book.setAuthor("李玲");
book.setWordCount(10000);
book.setUnitPrice(95.5);
book.setContentDescription("无"); //新建图书对象
Books book2 = new Books();
book2.setTitle("管理学");
book2.setISBN("2018012104");
book2.setAuthor("张青");
book2.setWordCount(10000);
book2.setUnitPrice(95.5);
book2.setContentDescription("无"); //双向维护关系
//设置关联关系,指定一到多的关联关系 ,因为会产生update语句,影响效率
//publisher.getBks().add(book);
//publisher.getBks().add(book2); //设置关联关系,指定多到一的关联关系
book.setPublisher(publisher);
book2.setPublisher(publisher); //执行保存,设置cascade级联属性之后,
//只保存一端即可(哪一端设置级联属性,可以只保存那一段,两端都设置,则任意一端都可以执行保存)
session.save(book);
session.save(book2);
}

③查询

/**
* 查询操作
* 查询某出版社出版的图书
*/
@Test
public void testBothManyToOneGet(){
Publishers publisher = (Publishers) session.get(Publishers.class, 1);
Iterator<Books> iterator = publisher.getBks().iterator();
System.out.println(publisher.getName() + "出版的图书有:");
while(iterator.hasNext()){
Books book = iterator.next();
System.out.println(book.getTitle());
}
}

④修改

/**
* 修改操作
* 把id为1的图书所对应的id为1出版社修改为id为2出版社
*/
@Test
public void testBothManyToOneUpdate(){
//获取出版社对象
Publishers publisher = (Publishers) session.get(Publishers.class, 1); //获取图书对象
Books book = (Books) session.get(Books.class, 1);
book.setPublisher(publisher); session.update(book);
}

⑤n端删除

/**
* 删除操作,删除图书信息
*
*/
@Test
public void testBothManyToOneDelete(){
Books book = (Books) session.get(Books.class, 12);
session.delete(book); }

⑥1端删除

/**
* 删除操作,删除出版社信息,以及出版社出版的图书
*
*/
@Test
public void testBothManyToOneDelete2(){
Publishers publisher = (Publishers) session.get(Publishers.class, 1);
session.delete(publisher);
}

五.总结

(双向n对1):其实就是单向n对1和单向1对n同时使用

1端

①实体类:添加集合属性

②映射文件:使用<set> 元素映射集合属性,

name属性指定映射的属性名

inverse属性设置为true代表一的一方不在拥有关联关系的控制权,而把控制权交给多的一方

<key> 元素指定外键,属性值要与n端的<many-to-one> 元素的column属性值一致,

使用<one-to-many class="Books"/> 元素映射关联关系

详细如下:

  <!--
cascade(级联)级联的意思是指两个对象之间的操作联运关系,对一个对象
执行了操作之后,对其指定的级联对象也需要执行相同的操作,
取值:all,none,save_update,delete。
1.all:代码在所有情况下都执行级联操作
2.none:在所有情况下都不执行级联操作
3.save-update:在保存和更新的情况下执行级联操作
4.delete:在删除的时候执行级联操作
inverse:属性设置为true代表一的一方不在拥有关联关系的控制权,
而把控制权交给多的一方
-->
<set name="bks" lazy="false" inverse="true" cascade="save-update,delete">
<!-- <key>指定外键 -->
<key column="PUBLISHER_ID" not-null="true"></key>
<one-to-many class="Books"/>
</set>

n端:

①实体类:添加一个n端实体类型的属性

②映射文件:使用<many-to-one> 元素映射实体类型的属性,column属性指定外键,class指定关联的类的名字。

详细如下:

<!-- 配置多对一关联映射 -->
<many-to-one name="publisher" class="Publishers"
column="PUBLISHER_ID" cascade="save-update">
</many-to-one>

Hibernate(10)_双向n对1(双向1对n)的更多相关文章

  1. Hibernate(12)_基于主键的双向1对1

    一.基于主键的双向1对1 1.介绍: 基于主键的映射策略:指一端的主键生成器使用 foreign 策略,表明根据"对方"的主键来生成自己的主键,自己并不能独立生成主键. <p ...

  2. Hibernate(11)_基于外键的双向1对1

    一.基于外键的双向1对1 对于基于外键的1-1关联,其外键可以存放在任意一边,在需要存放外键一端,增加many-to-one元素.为many-to-one元素增加unique="true&q ...

  3. 转:HIBERNATE一些_方法_@注解_代码示例---写的非常好

    HIBERNATE一些_方法_@注解_代码示例操作数据库7步骤 : 1 创建一个SessionFactory对象 2 创建Session对象 3 开启事务Transaction : hibernate ...

  4. Hibernate(9)_双向n对n

    1.概述 ①双向 n-n 关联需要两端都使用集合属性 ②双向n-n关联必须使用连接表 ③集合属性应增加 key 子元素用以映射外键列, 集合元素里还应增加many-to-many子元素关联实体类 ④在 ...

  5. hibernate 2 一对多、多对一 双向映射

    多对一或一对多中,在多的一方维护关系效率高 一:java实体类 1.Classes.java package cn.gs.ly.school.entity; import java.util.Set; ...

  6. 【Hibernate步步为营】--(一对多映射)之双向关联

    上篇文章讨论了单向关联的一对多映射,在一的一端维护双向的关系这样的做法尽管能实现可是存在非常多缺陷,首先生成非常多多余的SQL语句,由于多的一端不维护关系,仅仅有一的一端维护,在进行操作时一的一端会发 ...

  7. Hibernate双向一对多、双向多对多关联关系中的映射文件怎么写

    这里以一对多关联关系为例.以Country类为一端,Competition类为多端. 一个国家可以有多个赛事,但是一个赛事只能属于一个国家. Country类 public class Country ...

  8. Hibernate 注解(Annotations 二)一对一双向注解

    注解(Annotation),也叫元数据.一种代码级别的说明.它是JDK1.5及以后版本引入的一个特性,与类.接口.枚举是在同一个层次.它可以声明在包.类.字段.方法.局部变量.方法参数等的前面,用来 ...

  9. vue 双向绑定(v-model 双向绑定、.sync 双向绑定、.sync 传对象)

    1. v-model实现自定义组件双向绑定 v-model其实是个语法糖,如果没按照相应的规范定义组件,直接写v-model是不会生效的.再说一遍,类似于v-on:click可以简写成@click,v ...

随机推荐

  1. 期货大赛项目|三,autofac简单用法

    autofac是依赖注入 我们以前要引入一个dal层,是这么写的 private IDal _dao = new Dal() 我们可以看得出,这样写,我们的bll层不光依赖了接口IDal,还依赖了Da ...

  2. python全栈开发day87~91-整个流程梳理、CRM功能、知识点梳理

    1.流程 1. stark组件 1. 启动 2.注册 3.url设计 4.视图函数设计 1.展示数据头 2.展示数据 3.list_display功能实现 4.list_display_links 功 ...

  3. Bootstrap 框架、插件

    Bootstrap,前端工程师比较常用的框架.插件,根据它的定义,我们不妨这样理解,Bootstrap就是用于前端开发的一个模板,就是别人做好了我们直接可以搬过来直接使用或者根据自己需要略加修改设计自 ...

  4. AtCoder Grand Contest 11~17 做题小记

    原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-Grand-Contest-from-11-to-20.html UPD(2018-11-16): ...

  5. 062 SparkStream内部原理

    1.DStream 内部是一系列的RDD组成的,每个RDD与RDD的产生时间形成一个pair保存在内存中(下面有) RDD包含了对应时间段的所有block数据. 2.DStream下的方法 /** T ...

  6. 进程,线程,协程,io多路复用 总结

    并发:要做到同时服务多个客户端,有三种技术 1. 进程并行,只能开到当前cpu个数的进程,但能用来处理计算型任务 ,开销最大 2. 如果并行不必要,那么可以考虑用线程并发,单位开销比进程小很多 线程: ...

  7. 正则表达式在python中的简单使用

    正则表达式独立与编程语言,基本上所有的编程语言都实现了正则表达式的相关操作.在Python中正则表达式的表现为re模块: import re 其操作有三个方法: my_string = "h ...

  8. win10安装Oracle11g,出现INS-13001环境不满足最低要求问题

    今天安装Oracle11g,出现INS-13001环境不满足最低要求问题: 解决方法 在安装时点击setup.exe之后,出现了:[INS-13001]环境不满足最低要求 这时,打开你的解压后的dat ...

  9. jarvis OJ WEB题目writeup

    0x00前言 发现一个很好的ctf平台,题目感觉很有趣,学习了一波并记录一下 https://www.jarvisoj.com 0x01 Port51 题目要求是用51端口去访问该网页,注意下,要用具 ...

  10. 牛客练习赛35-函数的魔法-floyd

    函数的魔法 思路 :如果 可以从A到B最终 都会是233范围内的数字进行转换,注意 这里 建图 为单向图  这个运算未必符合交换关系. #include<bits/stdc++.h> us ...