单向n-n
n-n的关联必须使用连接表
与1-n映射类似,必须为set集合元素添加key子元素,指定CATEGORIES_ITEMS表
中参照CATEGORIES表的外键为GATEGORY_ID.与1-n关联映射不同的是,建立n-n关联时,集合中的元素使用many-to-many(而不使用one-to-mony).many-to-many子元素的class属性指定items集合中存放的是item对象,column属性指定属性指定CATEGORIES_ITEMS表中参照ITEMS表的外键为ITEM_ID
<set name=”items” table=”CATEGORIES_ITEMS” cascade=”save-update”>
<key column=”CATEGORY_ID“></key>
<many-to-many class=”Item” column=”item_id”/>
</set>
双向n-n关联
双向n-n关联需要两端都使用集合属性
双向n-n关联必须使用连接表
集合属性应增加key子元素泳衣映射外键列,集合元素里还应增加many-to-many
子元素关联实体类
在双向n-n关联的两边都需指定连接表的表名及外键列的列名,两个集合元素set的table元素的值必须指定 ,而且必须相同。Set元素的两个子元素:key和 many-to-many都必须指定column属性 , 其中,key和many-to-many分别制定本持久化类 和关联类在连接表中的外键列名 ,因此两边的key 与 many-to-many的 column属性交叉相同。
也就是说:一边的set元素的key的column值 为a,many-to-many的column为b;则另一边的set元素的key的column值b,many-to-many的column值为a,
对于双向n-n关联,必须把其中一段的inverse设置为true,否则两端都维护关联关系可能会造成主键冲突。
package com.atguigu.hibernate.n2n;
import java.util.HashSet;
import java.util.Set;
public class Category {
private Integer id;
private String name;
private Set<Item> items = new HashSet<Item>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Item> getItems() {
return items;
}
public void setItems(Set<Item> items) {
this.items = items;
}
}
package com.atguigu.hibernate.n2n;
import java.util.HashSet;
import java.util.Set;
public class Item {
private Integer id;
private String name;
private Set<Category> categories = new HashSet<Category>();
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<Category> getCategories() {
return categories;
}
public void setCategories(Set<Category> categories) {
this.categories = categories;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping package="com.atguigu.hibernate.n2n" >
<class name="Category" table="categories">
<id name="id" type="integer">
<column name="id"></column>
<generator class="native"></generator>
</id>
<property name="name" type="string">
<column name="name"></column>
</property>
<!-- table : 指定中间表 -->
<set name="items" table="categories_items">
<key>
<!-- 当前实体类在中间表中的外键的列名 -->
<column name="c_id"></column>
</key>
<!-- 使用many-to-many 指定多对多的关联关系,
column 指定Set 集合中的持久化类 在中间表中的外键列名
-->
<many-to-many class="Item" column="i_id" />
</set>
</class>
</hibernate-mapping>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd" >
<hibernate-mapping >
<class name="com.atguigu.hibernate.n2n.Item" table="items">
<id name="id" type="integer">
<column name="id"></column>
<generator class="native"></generator>
</id>
<property name="name" type="string">
<column name="name"></column>
</property>
<set name="categories" table="categories_items" inverse="true">
<key column="c_id"/>
<many-to-many class="com.atguigu.hibernate.n2n.Category" column="c_id" />
</set>
</class>
</hibernate-mapping>
package com.atguigu.hibernate.n2n;
import java.util.Set;
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 HibernateTest01 {
private SessionFactory sessionFactory;
private Session session;
private Transaction transaction;
@Before
public void init(){
Configuration conf = new Configuration().configure();
ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(conf.getProperties()).buildServiceRegistry();
sessionFactory = conf.buildSessionFactory(serviceRegistry);
session = sessionFactory.openSession();
transaction = session.beginTransaction();
}
@After
public void destroy(){
transaction.commit();
session.close();
sessionFactory.close();
}
@Test
public void testSave(){
Category category1 = new Category();
category1.setName("C-AA");
Category category2 = new Category();
category1.setName("C-BB");
Item item1 = new Item();
item1.setName("I-AA");
Item item2 = new Item();
item2.setName("I-BB");
//设定关联关系
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);
//一共打印输出8条语句 ,两边表中各有两条 ,中间表中有4条记录 一共8条插入语句
}
@Test
public void testGet(){
Category category = (Category) session.get(Category.class, 1);
System.out.println(category.getName());
//需要连接中间表
Set<Item> items = category.getItems();
System.out.println(items.size());
}
}