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>.工程< ...
随机推荐
- Java 中 static 和 volatile 关键字的区别?
static指的是类的静态成员,实例间共享 volatile跟Java的内存模型有关,线程执行时会将变量从主内存加载到线程工作内存,建立一个副本,在某个时刻写回.valatile指的每次都读取主内存的 ...
- C# 之设计原则
代码也需要有秩序,就像世界需要秩序,基于SOLID architecture principles. 一.SOLID原则 S.O.L.I.D.是一组面对面向对象设计的最佳实践的设计原则.术语来自Rob ...
- silverlight5 OOB 直接p/invoke实现串口通信
public class SerialWrapper : IDisposable { #region Enum public enum StopBits ...
- python写csv文件
name=['lucy','jacky','eric','man','san'] place=['chongqing','guangzhou','beijing','shanghai','shenzh ...
- excel追加数据
原本是想通过读取已存在的文件的行然后直接添加保存,发现结果会被覆盖. 后来查找方法发现需要复制原表. 函数参数: list:要添加的数据 filename:目标文件 sheet_index:默认表的第 ...
- 2018牛客网暑假ACM多校训练赛(第五场)F take 树状数组,期望
原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round5-F.html 题目传送门 - https://www.no ...
- datatable 转list ,list转datatable
方法一: public static IList<T> ConvertToModel(DataTable dt) { // 定义集合 ...
- Python3爬虫知识点总结
1.requests获取响应头的方法 eg:获取响应头信息 import requests res = request.head(url).headers print(res)
- 数据特征分析:3.统计分析 & 帕累托分析
1.统计分析 统计指标对定量数据进行统计描述,常从集中趋势和离中趋势两个方面进行分析 集中趋势度量 / 离中趋势度量 One.集中趋势度量 指一组数据向某一中心靠拢的倾向,核心在于寻找数据的代表值或中 ...
- URL简介
一般来说,http请求都会和URL地址有关,那么今天就来说说URL的组成部分. 实例:http://192.168.1.12/phpwind/searcher.php?keyword=phpwind& ...