映射多对多关联关系主要分为单向多对多关系和双向多对多关系,具体说明如下:


1. 单向n-n关联关系

  单向n-n关联关系的域模型和关系数据模型的概念示意图如下:

java同时插入关联表_关联关系


  实现:单向n-n关联关系必须使用中间连接表来实现,示例映射配置代码如下:

<!-- Category.hbm.xml核心配置代码 -->
<!-- table:指定中间表 -->
<set name="items" table="CATEGORYS_ITMES">
    <!-- 指定当前持久化类在中间表的外键列的名称,即指定CATEGORIES_ITEMS表中参照CATEGORIES表的外键为C_ID -->
    <key column="C_ID"></key>
    <!-- 使用many-to-many指定多对多的关联关系 -->
    <!-- column指定Set集合中持久化类在中间表的外键列的名称,即指定CATEGORIES_ITEMS表中参照ITEMS表的外键为I_ID -->
    <many-to-many class="Item" column="I_ID"></many-to-many>
</set>

  单向n-n关联关系的数据库操作测试代码如下所示:

@Test
public void testGet() {
    Category category = (Category) session.get(Category.class, 1);
    System.out.println(category.getName());

    // 查询items时需要连接中间表
    System.out.println(category.getItems());
}

@Test
public void testSave() {
    Category category1 = new Category();
    category1.setName("C-AA1");

    Category category2 = new Category();
    category2.setName("C-BB1");

    Item item1 = new Item();
    item1.setName("I-AA1");

    Item item2 = new Item();
    item2.setName("I-BB1");

    // 设定关联关系
    category1.getItems().add(item1);
    category1.getItems().add(item2);
    category2.getItems().add(item1);
    category2.getItems().add(item2);

    // 执行保存操作
    session.save(item1);
    session.save(item2);
    session.save(category1);
    session.save(category2);    
}

2. 双向n-n关联关系

  双向n-n关联关系的域模型和关系数据模型的概念示意图如下:

java同时插入关联表_外键_02


  实现:双向n-n关联关系需要两段都使用集合属性,且必须使用中间连接表来实现。

  注意:对于双向n-n关联关系,必须把其中一端的inverse属性设置为true,即放弃维护关联关系,否则会抛出异常。

  其中,示例映射配置代码如下:

<!-- Category.hbm.xml核心配置代码 -->
<!-- table:指定中间表 -->
<set name="items" table="CATEGORYS_ITMES">
    <!-- 指定当前持久化类在中间表的外键列的名称,即指定CATEGORIES_ITEMS表中参照CATEGORIES表的外键为C_ID -->
    <key column="C_ID"></key>
    <!-- 使用many-to-many指定多对多的关联关系 -->
    <!-- column指定Set集合中持久化类在中间表的外键列的名称,即指定CATEGORIES_ITEMS表中参照ITEMS表的外键为I_ID -->
    <many-to-many class="Item" column="I_ID"></many-to-many>
</set>
<!-- Item.hbm.xml核心配置代码 -->
<!-- table:指定中间表 -->
<!-- 需要在两端的任意一端添加inverse=true,否则抛出异常 -->
<!-- org.hibernate.exception.ConstraintViolationException -->
<set name="categories" table="CATEGORYS_ITMES" inverse="true">
    <!-- 当前持久化类在中间表的外键列的名称 -->
    <key column="I_ID"></key>
    <!-- 使用many-to-many指定多对多的关联关系 -->
    <!-- column指定Set集合中持久化类在中间表的外键列的名称 -->
    <many-to-many class="Category" column="C_ID"></many-to-many>
</set>

  单向n-n关联关系的数据库操作测试代码如下所示:

package com.qiaobc.hibernate.n2n;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class TestHibernate {

    private Session session = null;
    private Transaction transaction = null;
    private SessionFactory sessionFactory = null;

    @Before
    public void init() {
        // 获取session对象
        Configuration configuration = new Configuration().configure();
        ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
                .applySettings(configuration.getProperties())
                .buildServiceRegistry();
        sessionFactory = configuration.buildSessionFactory(serviceRegistry);
        session = sessionFactory.openSession();
        transaction = session.beginTransaction();
    }

    @Test
    public void testGet1() {
        Category category = (Category) session.get(Category.class, 1);
        System.out.println(category.getName());

        // 查询items时需要连接中间表
        System.out.println(category.getItems());
    }

    @Test
    public void testGet2() {
        Item item = (Item) session.get(Item.class, 1);
        System.out.println(item.getName());

        System.out.println(item.getCategories());
    }

    @Test
    public void testSave() {
        Category category1 = new Category();
        category1.setName("C-AA2");

        Category category2 = new Category();
        category2.setName("C-BB2");

        Item item1 = new Item();
        item1.setName("I-AA2");

        Item item2 = new Item();
        item2.setName("I-BB2");

        // 设定关联关系
        category1.getItems().add(item1);
        category1.getItems().add(item2);
        category2.getItems().add(item1);
        category2.getItems().add(item2);

        item1.getCategories().add(category1);
        item1.getCategories().add(category2);
        item2.getCategories().add(category1);
        item2.getCategories().add(category2);

        // 执行保存操作
        session.save(category1);
        session.save(category2);
        session.save(item1);
        session.save(item2);
    }

    @After
    public void destory() {
        transaction.commit();
        session.close();
        sessionFactory.close();
    }
}