Hibernate(9)_双向n对n
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的更多相关文章
- Hibernate(10)_双向n对1(双向1对n)
1.双向 1-n 与 双向 n-1 是完全相同的两种情形,这里使用双向多对一来演示 双向 1-n 需要在 1 的一端可以访问 n 的一端, 反之依然. 出版社和图书的关系:Publishers--Bo ...
- 转:HIBERNATE一些_方法_@注解_代码示例---写的非常好
HIBERNATE一些_方法_@注解_代码示例操作数据库7步骤 : 1 创建一个SessionFactory对象 2 创建Session对象 3 开启事务Transaction : hibernate ...
- hibernate多对一双向关联
关联是类(类的实例)之间的关系,表示有意义和值得关注的连接. 本系列将介绍Hibernate中主要的几种关联映射 Hibernate一对一主键单向关联Hibernate一对一主键双向关联Hiberna ...
- hibernate one-to-many many-to-one 双向注解
建表语句: DROP TABLE IF EXISTS `t_company`; CREATE TABLE `t_company` ( `companyId` ) unsigned NOT NULL A ...
- Java进阶知识12 Hibernate多对多双向关联(Annotation+XML实现)
1.Annotation 注解版 1.1.应用场景(Student-Teacher):当学生知道有哪些老师教,老师也知道自己教哪些学生时,可用双向关联 1.2.创建Teacher类和Student类 ...
- Hibernate(12)_基于主键的双向1对1
一.基于主键的双向1对1 1.介绍: 基于主键的映射策略:指一端的主键生成器使用 foreign 策略,表明根据"对方"的主键来生成自己的主键,自己并不能独立生成主键. <p ...
- Hibernate(11)_基于外键的双向1对1
一.基于外键的双向1对1 对于基于外键的1-1关联,其外键可以存放在任意一边,在需要存放外键一端,增加many-to-one元素.为many-to-one元素增加unique="true&q ...
- 【SSH系列】hibernate映射 -- 一对一双向关联映射
开篇前言 上篇博文[SSH进阶之路]hibernate映射--一对一单向关联映射,小编介绍了一对一的单向关联映射,单向是指只能从人(Person)这端加载身份证端(IdCard),但是反过来,不能从身 ...
- Hibernate多对多双向关联的配置
Hibernate的双向多对多关联有两种配置方法:那我们就来看看两种方案是如何配置的. 一.创建以各自类为类型的集合来关联 1.首先我们要在两个实体类(雇员<Emploee>.工程< ...
随机推荐
- Crystal Reports报表使用 [一]
1.Crystal Reports 是什么? Crystal Reports 是一个功能强大.动态和可操作的报表解决方案,它将帮助你通过网络设计.开发.可视化及发布报表,或嵌入到企业应用之中.有了它, ...
- vsftp 基于虚拟用户的ftp服务器 如何做配额
做配额的方法: 1,是用磁盘配额,但是虚拟用户好像没有好办法.只能应用于本地用户.与Vsftpd设置无关 2,文件夹限制大小,是占用的.这和Vsftpd没有关系 所以可以先把用户禁锢在自己工作目录里面 ...
- log4j快速入门
转自:http://blog.csdn.net/yanwushu/article/details/7581255 1.引言 在应用程序中添加日志记录总的来说基于三个目的: .监视代码中变量的变化情况, ...
- CSS规范 - 分类方法
CSS文件的分类和引用顺序 通常,一个项目我们只引用一个CSS,但是对于较大的项目,我们需要把CSS文件进行分类. 我们按照CSS的性质和用途,将CSS文件分成“公共型样式”.“特殊型样式”.“皮肤型 ...
- 20165220预备作业3 Linux安装及学习
首先对于这第三次作业而言,给我的准备时间确实不多,因为过年回老家6天,没有办法及时的进行学习和思考,回到家中便草草的看了下相关操作跟教程从而完成了作业,这次主要是学习一些基础操作,为开学的Java学习 ...
- 关于go get安装git golang项目时报错的处理办法
关于go get安装git golang项目时报错的处理办法 使用go get安装github上的项目时一般来说,不可避免会出错.各种错误的处理办法: 必须条件: 1.安装git并配置环境变量.下载地 ...
- jenkins+springboot+svn linux 自动化部署
需要下载 publish over ssh 插件(远程上传项目到服务器) Maven Integration plugin 插件(构建maven项目) 然后将各种配置配置好 最终项目在服务器上的路径是 ...
- 多媒体开发(8):调试FFmpeg
编译FFmpeg得到二进制文件,之后就是对二进制库的调用,这时FFmpeg就像一个黑盒子.作为程序员,难道不想研究一下FFmpeg的具体实现?比如是怎么拿到歌曲信息的.怎么解码的.怎么推流的,等等. ...
- linux进阶命令第一天
1.history -c 清空历史命令 保存的目录 vim ~/.bash_history history -w 立即把内存中的数据写入历史文件中 vim /etc/profile 默认配置文 ...
- 利用shell脚本实现nginx 的logs日志分割
Nginx 是一个非常轻量的 Web 服务器,体积小.性能高.速度快等诸多优点.但不足的是也存在缺点,比如其产生的访问日志文件一直就是一个,不会自动地进行切割,如果访问量很大的话,将 导致日志文件容量 ...