Hibernate4-7 映射多对多关联关系

本文介绍了在数据库中如何实现单向和双向多对多关联关系,包括使用中间连接表进行配置的方法,并提供了具体的映射配置代码示例。

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


1. 单向n-n关联关系

  单向n-n关联关系的域模型和关系数据模型的概念示意图如下:
这里写图片描述
  实现:单向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关联关系的域模型和关系数据模型的概念示意图如下:
这里写图片描述
  实现:双向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();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值