一般的設(shè)計中,多對多關(guān)聯(lián)映射需要一個中間表,hibernate會自動生成中間表,使用many-to-many標簽來表示多對多的關(guān)聯(lián)。在實體中,跟一對多一樣,也是用集合來表示。
一、單向多對多(工程hibernate_many2many_1)
這里我們使用用戶和角色的例子,相關(guān)映射:

實體類映射.png
數(shù)據(jù)庫表映射.JPG
Role.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.hibernate.Role" table="_role">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
</hibernate-mapping>
User.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.hibernate">
<class name="User" table="_user">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="roles" table="_user_role">
<key column="userid"></key>
<many-to-many class="Role" column="roleid"></many-to-many>
</set>
</class>
</hibernate-mapping>
說明:可以看到多對多的情況時我們是在數(shù)據(jù)庫中生成一張表專門維護映射關(guān)系。
測試:
Many2ManyTest.java
package cn.itcast.hibernate;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import org.hibernate.Session;
import org.junit.Test;
public class Many2ManyTest {
@Test
public void testSave1(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
Role r1 = new Role();
r1.setName("數(shù)據(jù)錄入人員");
session.save(r1);
Role r2 = new Role();
r2.setName("商務(wù)主管");
session.save(r2);
Role r3 = new Role();
r3.setName("大區(qū)經(jīng)理");
session.save(r3);
User u1 = new User();
u1.setName("張三");
Set u1Roles = new HashSet();
u1Roles.add(r1);
u1Roles.add(r2);
u1.setRoles(u1Roles);
User u2 = new User();
u2.setName("李四");
Set u2Roles = new HashSet();
u2Roles.add(r1);
u2Roles.add(r2);
u2.setRoles(u2Roles);
User u3 = new User();
u3.setName("王五");
Set u3Roles = new HashSet();
u3Roles.add(r3);
u3Roles.add(r3);
u3.setRoles(u3Roles);
session.save(u1);
session.save(u2);
session.save(u3);
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
@Test
public void testLoad1(){
Session session = null;
try{
session = HibernateUtils.getSession();
session.beginTransaction();
User user = (User) session.load(User.class, 1);
System.out.println(user.getName());
for(Iterator iter = user.getRoles().iterator(); iter.hasNext();){
Role role = (Role) iter.next();
System.out.println(role.getName());
}
session.getTransaction().commit();
}catch(Exception e){
e.printStackTrace();
session.getTransaction().rollback();
}finally{
HibernateUtils.closeSession(session);
}
}
}
說明:雖然我們生成了一個關(guān)系表,但是維護關(guān)系只是在User這邊進行維護,當(dāng)然我們也可以選擇在Role這邊維護。此時我們在存儲時應(yīng)該先將不維護關(guān)系的一方(這里是Role)存儲進去,然后再存儲User。同樣在查詢的時候也一樣,也是先查詢出User,然后再查出Role。
二、雙向多對多(工程hibernate_many2many_2)
雙向關(guān)系只需要在單向情況中的Role對象中維護一個保持用戶的set集合即可。存儲不變。

實體類映射.png
數(shù)據(jù)庫表映射.JPG
Role.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="cn.itcast.hibernate.Role" table="_role">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<set name="users">
<key column="roleid" />
<many-to-many class="cn.itcast.hibernate.User" column="userid"/>
</set>
</class>
</hibernate-mapping>
注意:中間表的字段名一定要相同。
測試:這里就不再細說了,和單向相比,這里我們就可以雙向存儲和查詢。同時我們也可以使用inverse屬性進行關(guān)系反轉(zhuǎn),只在一方維護關(guān)系,還有可以在set標簽中使用order-by屬性來進行排序:
<set name="users" table="_user_role" order-by="userid">。