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. CentOS7安装MySQL并设置远程登录

    在CentOS中默认安装有MariaDB,这个是MySQL的分支,但为了需要,还是要在系统中安装MySQL,而且安装完成之后可以直接覆盖掉MariaDB. 1 下载并安装MySQL官方的 Yum Re ...

  2. 铺放骨牌 uva11270

    题解: 插头dp裸题 没什么好说的啊就是n个二进制位表示状态 相比原先就是用2n个二进制位表示状态 蓝书上后面几题插头dp都挺烦的啊... 代码:

  3. C# 之 @ Assembly

    @ Assembly指定需要动态编译的类,在编译期间将程序集链接到 ASP.NET 应用程序页(例如网页.用户控件.母版页或 Global.asax 文件),使程序集的所有类和接口都在该页上可用. & ...

  4. C# 文件拖放到此程序的操作

       问题描述: 怎么写代码可以实现指定类型的文件通过鼠标拖放显示在程序的文本框中,如:选中3个文件(3个文件的格式有MP3和wma)拖到程序,程序的文本框显示这三个文件的路径...解决代码: thi ...

  5. mySql版本的相关问题:com.mysql.cj.jdbc.Driver和com.mysql.jdbc.Driver

    Mysql版本的相关问题:com.mysql.cj.jdbc.Driver和com.mysql.jdbc.Driver 1. 在使用mysql时,控制台日志报错如下: Loading class `c ...

  6. 爬虫之 beautifusoup4

    1. 使用方法 2.解析器 3. 详细用法 4. find_all方法 5. 遍历文档树

  7. C#调用WebService的简单方式

    WebServiceCallpublic class WebServiceCall { public void Call() { string url = "http://localhost ...

  8. C#中form窗体之间的传递几个方法

  9. JavaScript基础笔记(十四)最佳实践

    最佳实践 一)松散耦合 1.解耦HTML/JavaScript: 1)避免html种使用js 2)避免js种创建html 2.解耦CSS/JS 操作类 3.解耦应用逻辑和事件处理 以下是要牢记的应用和 ...

  10. 详解~实现Runnable方法创建线程之为什么要将Runnable接口的子类对象传递给Thread的构造函数

    /** * @author zhao * @TIME 0419 22:56 End *定义线程的第二种方法:实现Runnable接口(不考虑安全问题) *步骤:1,定义一个子类实现Runnable接口 ...