zoukankan      html  css  js  c++  java
  • 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

    在数据中执行查询:

  • 相关阅读:
    JDBC连接数据库的四种方式:DriverManager,DataSource,DBCP,C3P0
    下面代码打印的结果?
    当一个线程进入一个对象的synchronized方法A之后,其他线程是否可进入此对象的synchronized方法B?
    线程的sleep()方法和yield()方法有什么区别?
    今天,想说一说明星涉毒
    【译文】为什么用户体验文案在产品设计中如此重要?
    【译文】东京的外国工程师
    浅谈K8S cni和网络方案
    网易云易盾发布多国家多语种内容安全服务,助力中国互联网出海
    如何着手商业数据分析?
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/6959532.html
Copyright © 2011-2022 走看看