映射多对多关联关系主要分为单向多对多关系和双向多对多关系,具体说明如下:
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();
}
}