1.概述

①双向 n-n 关联需要两端都使用集合属性

②双向n-n关联必须使用连接表

③集合属性应增加 key 子元素用以映射外键列, 集合元素里还应增加many-to-many子元素关联实体类

④在双向 n-n 关联的两边都需指定连接表的表名及外键列的列名. 两个集合元素 set 的 table 元素的值必须指定,而且必须相同。set元素的两个子元素:key 和 many-to-many 都必须指定 column 属性,其中,key 和 many-to-many 分别指定本持久化类和关联类在连接表中的外键列名,因此两边的 key 与 many-to-many 的column属性交叉相同。也就是说,一边的set元素的key的 cloumn值为a,many-to-many 的 column 为b;则另一边的 set 元素的 key 的 column 值 b,many-to-many的 column 值为 a.

⑤对于双向 n-n 关联, 必须把其中一端的 inverse 设置为 true, 否则两端都维护关联关系可能会造成主键冲突.

2.实体类

Category.java

public class Category {

    private Integer id;
private String name;
//添加集合属性
private Set<Item> item = new HashSet<>();
//忽略getter和setter方法
...
}

Item.java

public class Item {

    private Integer id;
private String name;
//添加集合属性
private Set<Category> category = new HashSet<Category>();
//忽略getter和setter方法
...
}

3.映射文件

Category.hbm.xml

<!--
package指定实体类路径,在这个节点中的实体类就可以不用写全类名了,
auto-import设置为true(默认)是表示:使用HQL语句时,即使不指定具体的实体类,Hibernate会自动找到唯一的名称的实体映射,将其补全为全类名,
因为无法确定那个类是所需要的。
-->
<hibernate-mapping package="com.withXml.bothManyToMany.entity" auto-import="false"> <class name="Category" table="BOTH_CATEGORYS"> <id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id> <property name="name" type="java.lang.String">
<column name="NAME" />
</property> <!-- table:中间表 column:Category持久化类在中间表的外键-->
<set name="item" table="BOTH_CATEGORY_ITEM" inverse="true">
<key>
<column name="C_ID" />
</key>
<!-- 使用many-to-many指定多对多的关联关系,column:指定Set集合中的持久化类在中间表的外键列的名称,即Item持久化类在中间表的外键 -->
<many-to-many class="Item" column="I_ID"></many-to-many>
</set>
</class>
</hibernate-mapping>

Item.hbm.xml

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

    <class name="Item" table="BOTH_ITEMS">

        <id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id> <property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<!-- table:中间表 column:Item持久化类在中间表的外键-->
<set name="category" table="BOTH_CATEGORY_ITEM" inverse="false" lazy="true">
<key>
<column name="I_ID" />
</key>
<!-- 使用many-to-many指定多对多的关联关系,column:指定Set集合中的持久化类在中间表的外键列的名称,即Category持久化类在中间表的外键 -->
<many-to-many class="Category" column="C_ID"></many-to-many>
</set>
</class>
</hibernate-mapping>

4.CRUD测试

①保存操作

    @Test
public void testSave(){
Category category = new Category();
category.setName("C-AA");
Category category2 = new Category();
category2.setName("C-BB"); Item item = new Item();
item.setName("I-AA");
Item item2 = new Item();
item2.setName("I-BB"); //设定关联关系
category.getItem().add(item);
category.getItem().add(item2); category2.getItem().add(item);
category2.getItem().add(item2); item.getCategory().add(category);
item.getCategory().add(category2); item2.getCategory().add(category);
item2.getCategory().add(category2); //保存操作
session.save(category);
session.save(category2);
session.save(item);
session.save(item2); }

②获取

@Test
public void testGet(){
Category category = (Category) session.get(Category.class, 1);
System.out.println(category.getName());
//支持懒加载
System.out.println(category.getItem().toString()); //需要连接中间表
Set<Item> itmes = category.getItem();
System.out.println(itmes.size());
}

5.总结

①实体类:两端都需要添加集合属性

②映射文件:

Category端

<set> 元素:name属性指定该映射文件所对应的实体类的集合属性

table属性指定中间表,要与另一端映射文件中指定的中间表一致

<key> 元素:column属性指定外键,引用该映射文件对应数据表的主键,即自己的主键

<many-to-many>元素:class属性指定另一端的实体类,column指定外键,引用另一端实体类对应数据表的主键,即对方的主键,该值要与对方<key> 元素值一致

详细如下:

 <!-- table:中间表  column:Category持久化类在中间表的外键-->
<set name="item" table="BOTH_CATEGORY_ITEM" inverse="true">
<key>
<column name="C_ID" />
</key>
<!-- 使用many-to-many指定多对多的关联关系,column:指定Set集合中的持久化类在中间表的外键列的名称,即Item持久化类在中间表的外键 -->
<many-to-many class="Item" column="I_ID"></many-to-many>
</set>

Item端

<set> 元素:name属性指定该映射文件所对应的实体类的集合属性

table属性指定中间表,要与另一端映射文件中指定的中间表一致

<key> 元素:column属性指定外键,引用该映射文件对应数据表的主键,即自己的主键

<many-to-many>元素:class属性指定另一端的实体类,column指定外键,引用另一端实体类对应数据表的主键,即对方的主键,该值要与对方<key> 元素值一致

详细如下:


<!-- table:中间表 column:Item持久化类在中间表的外键-->
<set name="category" table="BOTH_CATEGORY_ITEM" inverse="false" lazy="true">
<key>
<column name="I_ID" />
</key>
<!-- 使用many-to-many指定多对多的关联关系,column:指定Set集合中的持久化类在中间表的外键列的名称,即Category持久化类在中间表的外键 -->
<many-to-many class="Category" column="C_ID"></many-to-many>
</set>

③必须把其中一端的 inverse 设置为 true, 否则两端都维护关联关系可能会造成主键冲突.

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

  1. Hibernate(10)_双向n对1(双向1对n)

    1.双向 1-n 与 双向 n-1 是完全相同的两种情形,这里使用双向多对一来演示 双向 1-n 需要在 1 的一端可以访问 n 的一端, 反之依然. 出版社和图书的关系:Publishers--Bo ...

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

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

  3. hibernate多对一双向关联

    关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...

  4. hibernate one-to-many many-to-one 双向注解

    建表语句: DROP TABLE IF EXISTS `t_company`; CREATE TABLE `t_company` ( `companyId` ) unsigned NOT NULL A ...

  5. Java进阶知识12 Hibernate多对多双向关联(Annotation+XML实现)

    1.Annotation 注解版 1.1.应用场景(Student-Teacher):当学生知道有哪些老师教,老师也知道自己教哪些学生时,可用双向关联 1.2.创建Teacher类和Student类 ...

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

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

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

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

  8. 【SSH系列】hibernate映射 -- 一对一双向关联映射

    开篇前言 上篇博文[SSH进阶之路]hibernate映射--一对一单向关联映射,小编介绍了一对一的单向关联映射,单向是指只能从人(Person)这端加载身份证端(IdCard),但是反过来,不能从身 ...

  9. Hibernate多对多双向关联的配置

    Hibernate的双向多对多关联有两种配置方法:那我们就来看看两种方案是如何配置的.  一.创建以各自类为类型的集合来关联 1.首先我们要在两个实体类(雇员<Emploee>.工程< ...

随机推荐

  1. Android抓包方法(转)

    Android抓包方法(转) 作者:Findyou 地址:http://www.cnblogs.com/findyou/p/3491014.html 前言: 做前端测试,基本要求会抓包,会分析请求数据 ...

  2. tmux 安装

    安装libevent wget https://github.com/downloads/libevent/libevent/libevent-2.0.21-stable.tar.gz tar xzv ...

  3. POJ1459 Power Network 网络流 最大流

    原文链接http://www.cnblogs.com/zhouzhendong/p/8326021.html 题目传送门 - POJ1459 题意概括 多组数据. 对于每一组数据,首先一个数n,表示有 ...

  4. c#一步一步实现ORM

    本篇适合新手了解学习orm.欢迎指正,交流学习. 现有的优秀的orm有很多. EF:特点是高度自动化,缺点是有点重. Nhibnate:缺点是要写很多的配置. drapper:最快的orm.但是自动化 ...

  5. 003.MySQL高可用主从复制新增slave

    一 基础环境 主机名 系统版本 MySQL版本 主机IP master CentOS 6.8 MySQL 5.6 172.24.8.10 slave01 CentOS 6.8 MySQL 5.6 17 ...

  6. spring_AOP_annotation

    例子下载 beans.xml 首先,在配置文件配置好下面的配置 <?xml version="1.0" encoding="UTF-8"?> < ...

  7. 声明式调用---Feign

    Feign:Feign是一种声明式.模板化的HTTP客户端. 用我的理解来说,Feign的功能类似dubbo暴露服务,但是与dubbo稍有不同的是Feign是HTTP REST接口的形式暴露的. 这一 ...

  8. UVA 220 Othello

    题意:输入n,代表次数,每次输入8*8的棋盘,处理3种命令:①L:打印所有合法操作,②M:放棋子,③Q:打印棋盘然后退出. 思路:①用字符数组存棋盘,整型数组存合法位置. ②查找的方法:当前玩家为cu ...

  9. 如何安装使用FastReport

    1.百度搜索FastReport.Net4.0下载,或者到我的云盘去下载. 2.解压后打开目录:FastReport.Net4.0_Full.安装:FRNetDemo2010.msi 3.把FastR ...

  10. RabbitMQ事物模式

    Rabbit的消息确认机制(事务+confirm)在rabbmitmq中我们可以通过持久化数据解决rabbitmq服务器异常的数据丢失问题问题:生产者将消息发送出去之后消息到底有没有到达rabbitm ...