Hibernate(十):n-n关联关系

  • 背景:

  在实际开发中我们会遇到表的多对多关联,比如:一篇博客文章,它可以同时属于JAVA分类、Hibernate分类。

  因此,我们在hibernate的学习文章系列中,需要学会如何使用hibernate来实现多对多的关联关系。

  在hibernate实现多对多的关联关系中,也是需要创建一个中间表来存储、维护两张表的多对多的关系。具体实现有两种可选方案:单向多对多、双向多对多。

  • 单向多对多:

 新建一个java project,定义项目名称为:hibernate07;在src下添加hibernate.cfg.xml

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE hibernate-configuration PUBLIC
 3         "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
 4         "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
 5 <hibernate-configuration>
 6     <session-factory>
 7         <property name="hibernate.connection.username">root</property>
 8         <property name="hibernate.connection.password">123456</property>
 9         <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
10         <property name="hibernate.connection.url">jdbc:mysql://localhost/hibernate_01</property>
11 
12         <!-- <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> 
13             <property name="hibernate.dialect">org.hibernate.dialect.MySQLInnoDBDialect</property> -->
14         <property name="hibernate.dialect">org.hibernate.dialect.MySQL5InnoDBDialect</property>
15 
16         <property name="hibernate.show_sql">true</property>
17 
18         <property name="hibernate.format_sql">true</property>
19 
20         <property name="hibernate.hbm2ddl.auto">update</property>
21 
22         <property name="hibernate.current_session_context_class">thread</property>
23 
24         <property name="hibernate.c3p0.max_size">500</property>
25         <property name="hibernate.c3p0.min_size">20</property>
26         <property name="hibernate.c3p0.max_statements">10</property>
27         <property name="hibernate.c3p0.timeout">2000</property>
28         <property name="hibernate.c3p0.idle_test_period">2000</property>
29         <property name="hibernate.c3p0.acquire_increment">10</property>
30 
31         <mapping resource="com/dx/hibernate06/n2n/ProductCategory.hbm.xml" />        
32         <mapping resource="com/dx/hibernate06/n2n/ProductItem.hbm.xml" />
33             
34     </session-factory>
35 </hibernate-configuration>
View Code

在src下创建包com.dx.hibernate06.n2n,在包下创建:

ProductCategory.java(在category这个类中创建了一个Set<ProductItem> productItems 属性)

 1 package com.dx.hibernate06.n2n;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 public class ProductCategory {
 7     private Integer id;
 8     private String name;
 9     private String detail;
10     private Set<ProductItem> productItems = new HashSet<>();
11 
12     public ProductCategory() {
13 
14     }
15 
16     public ProductCategory(String name, String detail) {
17         super();
18         this.name = name;
19         this.detail = detail;
20     }
21 
22     public Integer getId() {
23         return id;
24     }
25 
26     public void setId(Integer id) {
27         this.id = id;
28     }
29 
30     public String getName() {
31         return name;
32     }
33 
34     public void setName(String name) {
35         this.name = name;
36     }
37 
38     public String getDetail() {
39         return detail;
40     }
41 
42     public void setDetail(String detail) {
43         this.detail = detail;
44     }
45 
46     public Set<ProductItem> getProductItems() {
47         return productItems;
48     }
49 
50     public void setProductItems(Set<ProductItem> productItems) {
51         this.productItems = productItems;
52     }
53 
54 }
View Code

ProductCategory.hbm.xml

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 <!-- Generated 2017-6-7 22:33:53 by Hibernate Tools 3.5.0.Final -->
 5 <hibernate-mapping package="com.dx.hibernate06.n2n">
 6     <class name="ProductCategory" table="PRODUCT_CATEGORY">
 7         <id name="id" type="java.lang.Integer">
 8             <column name="ID" />
 9             <generator class="native" />
10         </id>
11         <property name="name" type="java.lang.String">
12             <column name="NAME" />
13         </property>
14         <property name="detail" type="java.lang.String">
15             <column name="DETAIL" />
16         </property>
17 
18         <set name="productItems" table="PRODUCT_CATEGORY_ITEM">
19             <key>
20                 <column name="CATEGORY_ID" />
21             </key>
22             <many-to-many class="ProductItem" column="ITEM_ID"></many-to-many>
23         </set>
24     </class>
25 </hibernate-mapping>
View Code

备注:在ProductCategory.hbm.xml的set节点我们定义的table属性,并定义了many-to-many节点用来指向ProductItem。

ProductItem.java

 1 package com.dx.hibernate06.n2n;
 2 
 3 public class ProductItem {
 4     private Integer id;
 5     private String title;
 6     private double price;
 7 
 8     public ProductItem() {
 9     }
10 
11     public ProductItem(String title, double price) {
12         super();
13         this.title = title;
14         this.price = price;
15     }
16 
17     public Integer getId() {
18         return id;
19     }
20 
21     public void setId(Integer id) {
22         this.id = id;
23     }
24 
25     public String getTitle() {
26         return title;
27     }
28 
29     public void setTitle(String title) {
30         this.title = title;
31     }
32 
33     public double getPrice() {
34         return price;
35     }
36 
37     public void setPrice(double price) {
38         this.price = price;
39     }
40 
41 }
View Code

ProductItem.hbm.xml

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 <!-- Generated 2017-6-7 22:33:53 by Hibernate Tools 3.5.0.Final -->
 5 <hibernate-mapping>
 6     <class name="com.dx.hibernate06.n2n.ProductItem" table="PRODUCT_ITEM">
 7         <id name="id" type="java.lang.Integer">
 8             <column name="ID" />
 9             <generator class="native" />
10         </id>
11         <property name="title" type="java.lang.String">
12             <column name="TITLE" />
13         </property>
14         <property name="price" type="double">
15             <column name="PRICE" />
16         </property>
17     </class>
18 </hibernate-mapping>
View Code

测试类TestMain.java 

 1 package com.dx.hibernate06.n2n;
 2 
 3 import java.util.Date;
 4 import java.util.Set;
 5 
 6 import org.hibernate.Session;
 7 import org.hibernate.SessionFactory;
 8 import org.hibernate.Transaction;
 9 import org.hibernate.boot.Metadata;
10 import org.hibernate.boot.MetadataSources;
11 import org.hibernate.boot.model.naming.ImplicitNamingStrategyComponentPathImpl;
12 import org.hibernate.boot.registry.StandardServiceRegistry;
13 import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
14 import org.hibernate.metamodel.internal.MapMember;
15 import org.junit.After;
16 import org.junit.Before;
17 import org.junit.Test;
18 
19 public class TestMain {
20     private SessionFactory sessionFactory = null;
21     private Session session = null;
22     private Transaction transaction = null;
23 
24     @Before
25     public void init() {
26         StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder().configure().build();
27         Metadata metadata = new MetadataSources(standardRegistry).getMetadataBuilder().applyImplicitNamingStrategy(ImplicitNamingStrategyComponentPathImpl.INSTANCE).build();
28 
29         sessionFactory = metadata.getSessionFactoryBuilder().build();
30         session = sessionFactory.getCurrentSession();
31         transaction = session.beginTransaction();
32     }
33 
34     @After
35     public void destory() {
36         transaction.commit();
37         session.close();
38         sessionFactory.close();
39     }
40 }
View Code

 测试代码:

添加测试函数1:

 1     @Test
 2     public void testInsert() {
 3         ProductCategory category1 = new ProductCategory();
 4         category1.setName("category1");
 5         category1.setDetail("Detail");
 6 
 7         ProductCategory category2 = new ProductCategory();
 8         category2.setName("category2");
 9         category2.setDetail("Detail");
10 
11         ProductItem item1 = new ProductItem();
12         item1.setTitle("item1");
13         item1.setPrice(110.00);
14 
15         ProductItem item2 = new ProductItem();
16         item2.setTitle("item2");
17         item2.setPrice(110.00);
18 
19         category1.getProductItems().add(item1);
20         category1.getProductItems().add(item2);
21 
22         category2.getProductItems().add(item1);
23         category2.getProductItems().add(item2);
24 
25         session.save(category1);
26         session.save(category2);
27 
28         session.save(item1);
29         session.save(item2);
30     }

控制台打印sql

 1 Hibernate: 
 2     
 3     create table PRODUCT_CATEGORY (
 4        ID integer not null auto_increment,
 5         NAME varchar(255),
 6         DETAIL varchar(255),
 7         primary key (ID)
 8     ) engine=InnoDB
 9 Hibernate: 
10     
11     create table PRODUCT_CATEGORY_ITEM (
12        CATEGORY_ID integer not null,
13         ITEM_ID integer not null,
14         primary key (CATEGORY_ID, ITEM_ID)
15     ) engine=InnoDB
16 Hibernate: 
17     
18     create table PRODUCT_ITEM (
19        ID integer not null auto_increment,
20         TITLE varchar(255),
21         PRICE double precision,
22         primary key (ID)
23     ) engine=InnoDB
24 Hibernate: 
25     
26     alter table PRODUCT_CATEGORY_ITEM 
27        add constraint FKgqq9f2yg5b52m390yk15c8u28 
28        foreign key (ITEM_ID) 
29        references PRODUCT_ITEM (ID)
30 Hibernate: 
31     
32     alter table PRODUCT_CATEGORY_ITEM 
33        add constraint FKtajc52s55t4fk8864s63hsuv2 
34        foreign key (CATEGORY_ID) 
35        references PRODUCT_CATEGORY (ID)
View Code

查询数据库结果信息:

添加测试函数2:

1     @Test
2     public void testSelect() {
3         ProductCategory category = (ProductCategory) session.get(ProductCategory.class, 1);
4         System.out.println(category.getName());
5 
6         System.out.println(category.getProductItems().size());
7     }

后台执行sql及结果:

 1 Hibernate: 
 2     select
 3         productcat0_.ID as ID1_0_0_,
 4         productcat0_.NAME as NAME2_0_0_,
 5         productcat0_.DETAIL as DETAIL3_0_0_ 
 6     from
 7         PRODUCT_CATEGORY productcat0_ 
 8     where
 9         productcat0_.ID=?
10 category1
11 Hibernate: 
12     select
13         productite0_.CATEGORY_ID as CATEGORY1_1_0_,
14         productite0_.ITEM_ID as ITEM_ID2_1_0_,
15         productite1_.ID as ID1_2_1_,
16         productite1_.TITLE as TITLE2_2_1_,
17         productite1_.PRICE as PRICE3_2_1_ 
18     from
19         PRODUCT_CATEGORY_ITEM productite0_ 
20     inner join
21         PRODUCT_ITEM productite1_ 
22             on productite0_.ITEM_ID=productite1_.ID 
23     where
24         productite0_.CATEGORY_ID=?
25 2
  • 双向多对多:

 实现双向多对多,需要再ProductItem的另一端也定义Set属性:Set<ProductCategory> productCategories。还需要在ProductItem.hbm.xml中添加set节点,节点属性配置与ProductCategory.hbm.xml中set节点配置对调。

修改ProductItem.java(在类中添加属性:Set<ProductCategory> productCategories):

 1 package com.dx.hibernate06.n2n;
 2 
 3 import java.util.HashSet;
 4 import java.util.Set;
 5 
 6 public class ProductItem {
 7     private Integer id;
 8     private String title;
 9     private double price;
10     private Set<ProductCategory> productCategories = new HashSet<>();
11 
12     public ProductItem() {
13     }
14 
15     public ProductItem(String title, double price) {
16         super();
17         this.title = title;
18         this.price = price;
19     }
20 
21     public Integer getId() {
22         return id;
23     }
24 
25     public void setId(Integer id) {
26         this.id = id;
27     }
28 
29     public String getTitle() {
30         return title;
31     }
32 
33     public void setTitle(String title) {
34         this.title = title;
35     }
36 
37     public double getPrice() {
38         return price;
39     }
40 
41     public void setPrice(double price) {
42         this.price = price;
43     }
44 
45     public Set<ProductCategory> getProductCategories() {
46         return productCategories;
47     }
48 
49     public void setProductCategories(Set<ProductCategory> productCategories) {
50         this.productCategories = productCategories;
51     }
52 
53 }
View Code

修改ProductItem.hbm.xml配置文件(添加set节点,并在ProductItem.hbm.xml或者ProductCategory.hbm.xml的set节点中添加属性inverse="true"):

 1 <?xml version="1.0"?>
 2 <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
 3 "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
 4 <!-- Generated 2017-6-7 22:33:53 by Hibernate Tools 3.5.0.Final -->
 5 <hibernate-mapping>
 6     <class name="com.dx.hibernate06.n2n.ProductItem" table="PRODUCT_ITEM">
 7         <id name="id" type="java.lang.Integer">
 8             <column name="ID" />
 9             <generator class="native" />
10         </id>
11         <property name="title" type="java.lang.String">
12             <column name="TITLE" />
13         </property>
14         <property name="price" type="double">
15             <column name="PRICE" />
16         </property>
17 
18         <set name="productCategories" table="PRODUCT_CATEGORY_ITEM" inverse="true">
19             <key>
20                 <column name="ITEM_ID" />
21             </key>
22             <many-to-many class="com.dx.hibernate06.n2n.ProductCategory" column="CATEGORY_ID"></many-to-many>
23         </set>
24     </class>
25 </hibernate-mapping>

删除数据中的表,之后添加测试函数。

mysql> drop table PRODUCT_CATEGORY_ITEM;
Query OK, 0 rows affected (0.02 sec)mysql> drop table PRODUCT_CATEGORY;
Query OK, 0 rows affected (0.02 sec)mysql> drop table PRODUCT_ITEM;
Query OK, 0 rows affected (0.01 sec)mysql> show tables;
+------------------------+
| Tables_in_hibernate_01 |
+------------------------+
| customer               |
| deparments             |
| managers               |
| member                 |
| memberdetail           |
| news                   |
| orders                 |
+------------------------+
7 rows in set (0.00 sec)mysql>

 测试代码: 

添加测试函数1:

 1     @Test
 2     public void testInsert() {
 3         ProductCategory category1 = new ProductCategory();
 4         category1.setName("category1");
 5         category1.setDetail("Detail");
 6 
 7         ProductCategory category2 = new ProductCategory();
 8         category2.setName("category2");
 9         category2.setDetail("Detail");
10 
11         ProductItem item1 = new ProductItem();
12         item1.setTitle("item1");
13         item1.setPrice(110.00);
14 
15         ProductItem item2 = new ProductItem();
16         item2.setTitle("item2");
17         item2.setPrice(110.00);
18 
19         category1.getProductItems().add(item1);
20         category1.getProductItems().add(item2);
21         category2.getProductItems().add(item1);
22         category2.getProductItems().add(item2);
23 
24         item1.getProductCategories().add(category1);
25         item1.getProductCategories().add(category2);
26         item2.getProductCategories().add(category1);
27         item2.getProductCategories().add(category2);
28         
29         session.save(category1);
30         session.save(category2);
31 
32         session.save(item1);
33         session.save(item2);
34     }

测试执行sql:

 1 Hibernate: 
 2     
 3     create table PRODUCT_CATEGORY (
 4        ID integer not null auto_increment,
 5         NAME varchar(255),
 6         DETAIL varchar(255),
 7         primary key (ID)
 8     ) engine=InnoDB
 9 Hibernate: 
10     
11     create table PRODUCT_CATEGORY_ITEM (
12        CATEGORY_ID integer not null,
13         ITEM_ID integer not null,
14         primary key (CATEGORY_ID, ITEM_ID)
15     ) engine=InnoDB
16 Hibernate: 
17     
18     create table PRODUCT_ITEM (
19        ID integer not null auto_increment,
20         TITLE varchar(255),
21         PRICE double precision,
22         primary key (ID)
23     ) engine=InnoDB
24 Hibernate: 
25     
26     alter table PRODUCT_CATEGORY_ITEM 
27        add constraint FKgqq9f2yg5b52m390yk15c8u28 
28        foreign key (ITEM_ID) 
29        references PRODUCT_ITEM (ID)
30 Hibernate: 
31     
32     alter table PRODUCT_CATEGORY_ITEM 
33        add constraint FKtajc52s55t4fk8864s63hsuv2 
34        foreign key (CATEGORY_ID) 
35        references PRODUCT_CATEGORY (ID)
36 Hibernate: 
37     insert 
38     into
39         PRODUCT_CATEGORY
40         (NAME, DETAIL) 
41     values
42         (?, ?)
43 Hibernate: 
44     insert 
45     into
46         PRODUCT_CATEGORY
47         (NAME, DETAIL) 
48     values
49         (?, ?)
50 Hibernate: 
51     insert 
52     into
53         PRODUCT_ITEM
54         (TITLE, PRICE) 
55     values
56         (?, ?)
57 Hibernate: 
58     insert 
59     into
60         PRODUCT_ITEM
61         (TITLE, PRICE) 
62     values
63         (?, ?)
64 Hibernate: 
65     insert 
66     into
67         PRODUCT_CATEGORY_ITEM
68         (CATEGORY_ID, ITEM_ID) 
69     values
70         (?, ?)
71 Hibernate: 
72     insert 
73     into
74         PRODUCT_CATEGORY_ITEM
75         (CATEGORY_ID, ITEM_ID) 
76     values
77         (?, ?)
78 Hibernate: 
79     insert 
80     into
81         PRODUCT_CATEGORY_ITEM
82         (CATEGORY_ID, ITEM_ID) 
83     values
84         (?, ?)
85 Hibernate: 
86     insert 
87     into
88         PRODUCT_CATEGORY_ITEM
89         (CATEGORY_ID, ITEM_ID) 
90     values
91         (?, ?)
View Code

在数据中执行查询:

 

转载于:https://www.cnblogs.com/yy3b2007com/p/6959532.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/269221.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT 开发基于高德智感 ITA SDK 的红外模组应用

QT 开发基于高德智感 ITA SDK 的红外模组应用 1.把创建的工程 .pro 文件打开&#xff0c;在文本编辑区域点击鼠标右键弹出操作选项框&#xff0c; 点击 “Add Libraray…” 2.选择“External Libraray ”, 点击 “Next” 3.在弹出框点击选择Linux Platform, Library Type 选…

webpack第一节(4)

每次修改了代码都需要重新手动打包&#xff0c;这样很麻烦&#xff0c;不符合webpack的初衷&#xff0c;我们查看webpack帮助看看有没有可以自动运行的方法 输入 webpack -help 可以发现有个 --watch方法 它的解释是监听系统文件改变 我们试一试 现在监听进程一直在运行 我们改…

T.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.Reflectio

There is no getter for property named * in class java.lang.String&#xff0c;此错误之所以出现&#xff0c;是因为mybatis在对parameterType"String"的sql语句做了限制&#xff0c;假如你使用<when test"username ! null">这样的条件判断时&…

【新媒体】现阶段新闻聚合的玩法

郑昀 20070824<?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" />新浪科技主编曹增辉的《新闻聚合的门槛》论及了玩聚所处的一些大环境之先天不足&#xff0c;主要是环境门槛、细分市场的门槛&#xff0c;以及入口问题。我的理解呢…

1 java开发工具IDEA的使用

IntelliJ IDEA 2017.1汉化破解版安装图文教程(附汉化补丁) 注册码:http://idea.lanyus.com/ 点击在线生成 IntelliJ IDEA 2017.1正式版发布了&#xff0c;在新增功能方面值得关注的亮点有对Java 9的支持&#xff0c;以及对 Spring Data 支持的改进。在增强功能上&#xff0c;除…

[转]权限树中Checkbox的操作[Asp.Net2.0]

转自:http://jeffamy.cnblogs.com/archive/2006/06/17/428387.html原文如下:这里使用asp.net2.0的TreeView控件结合JavaScript实现权限树的部分功能。假设权限树中有如下三条规则&#xff1a;1、该节点可以访问&#xff0c;则他的父节点也必能访问&#xff1b;2、该节点可以访问…

java -XX:+PrintFlagsInitial该命令可以查看所有JVM参数启动的初始值

java -XX:PrintFlagsInitial 该命令可以查看所有JVM参数启动的初始值 [Global flags]intx ActiveProcessorCount -1 {product}uintx AdaptiveSizeDecrementScaleFactor 4 …

影视资料

影视资料栏目属于一把刀实用查询大全的娱乐类别。中国最大的影视资料数据库和影人明星数据库&#xff0c;囊括包括中国、中国香港、中国台湾、美国、日本、韩国、英国等全球数十个国家的电影、电视资料及相关海报、剧照。转载于:https://blog.51cto.com/65000/41062

VA Code编写html(1)

<html><head><title>my webside</title><!--win‘/’注释行--><!--防止中文乱码在head中添加如下代码--><meta charset"utf-8"><body><!--<img src"image/1.jpg" alt"未找到图片">加载…

MFC 使用 Picture control 显示图片和数据流

一、使用现有的图片文件显示在 界面 picture 控件 在MFC picture 加载bitmap 图片方法图片可以是从资源文件夹来的&#xff0c;也可以是文件路径等CBitMap 载入图像接口 有两种方式 BOOL LoadBitmap(LPCTSTR lpszResourceName); // 资源文件名 BOOL LoadBitmap(UINT nIDResour…

OSPF动态路由协议入门简介

——随着Internet技术在全球范围的飞速发展&#xff0c;OSPF已成为目前Internet广域网和Intranet企业网采用最多、应用最广泛的路由协议之一。OSPF&#xff08;Open Shortest Path First&#xff09;路由协议是由IETF&#xff08;Internet Engineering Task Force&#xff09;I…

解决 413 Request Entity Too Large(请求实体太大)

今天做上传视频&#xff0c;报错413 Request Entity Too Large 我们可以看到请求的body的大小&#xff0c;在Content-Length后显示&#xff0c;Nginx默认的request body为1M&#xff0c;小于我们上传的大小 解决方案 找到自己主机的nginx.conf配置文件&#xff0c;打开 在http…

MFC 让界面点击无效

把 Disableed 设置为 True 就是让界面不再接受鼠标等控制。

关于 There is no getter for property named ‘id‘ in ‘class java.lang.Integer‘

errMsgorg.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named parentId in class java.lang.Integer 加上 Param("")注解

高德 ASIC 256 模组快门状态实时获取方案

1、快门状态命令 这个状态是由 ASIC 程序操作快门后记录的&#xff0c;如果是断电下的意外振动关闭是无法记录的 2、快门状态获取解决办法 根据快门闭合后的特征: 1) 温度均匀&#xff0c; 目标物体温度基本等于快门温度 2) 图像无轮廓线条和角点 3、快门状态实时检测线程 实…