hibernate 3.2(9)多対多相関マッピング

6681 ワード

原作者:http://www.verydemo.com/demo_c 146_i 2174.
 
 
 
ユーザーとキャラクターはマルチペアの関係に属しています。1人のユーザは複数のキャラクターを持ち、1つのキャラクターは複数のユーザに属してもいいです。
 
public class User {
	private int userid;
	private String username;
	private Set roles;
	getter and setter..
	
}
 
 
public class Role {
	private int roleid;
	private String rolename;
                getter & setter
}
 
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="com.wyx.hibernate">
	<class name="User" table="t_User">
		<id name="userid">
			<generator  class="native"/>
		</id>
		<property name="username"/>
		<set name="roles" table="t_User_Role" cascade="all">
			<key column="userid" />
			<many-to-many class="Role" column="roleid"/>
		</set>
	</class>
</hibernate-mapping>
セットラベルのnameはuserの関連フィールドを指し、setは中間テーブルを表し、テーブルの名前をtableで指定し、keyのcolumn属性を外キーとしてuserテーブルのuserid、many-to-mangのcolumnを外キーとしてroleテーブルのroidを指し、複合マスターキーを構成しています。
 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 package="com.wyx.hibernate">
	<class name="Role" table="t_Role">
		<id name="roleid">
			<generator class="native"/>
		</id>
		<property name="rolename"/>
	</class>
</hibernate-mapping>
 ペアの多さをテストして、user側から保存します。
 
public void testSave(){
		Session session = HibernateUtils.getSession();
		try {
			session.beginTransaction();
			
			Role role1 = new Role();
			role1.setRolename("   ");
			//session.save(role1);
			Role role2 = new Role();
			role2.setRolename("   ");
			//session.save(role2);
			Set roles = new HashSet<Role>();
			roles.add(role1);
			roles.add(role2);
			
			User user =new User();
			user.setUsername("  ");
			user.setRoles(roles);
			session.save(user);
			session.getTransaction().commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
		
	}
印刷出力:
ヒベルナ:insert into t_User(username)values(?)Hbernate:insert into t_Role(rolename)values(?)Hbernate:insert into t_Role(rolename)values(?)Hbernate:insert into t_User_Role(userid,roleid)values(?,?)Hbernate:insert into t_User_Role(userid,roleid)values(?、?)  
 
 ペアのマルチロードをテストして、user側から保存します。
public void testLoad(){
		Session session = HibernateUtils.getSession();
		try {
			session.beginTransaction();
			User user = (User)session.load(User.class, 1);
			Set<Role> roles = user.getRoles();
			System.out.println("user.username = " + user.getUsername());
			for(Iterator<Role> iter = roles.iterator(); iter.hasNext();){
				Role role = iter.next();
				System.out.println("user.role.rolename = " + role.getRolename());
			}
			session.getTransaction().commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
		
	}
 
印刷出力:
…………
 
 
 
双方向多対多相関マッピングは一方向の基本と一致しています。二重送信でsetセットを入れて関連関係を保存していますが、格納フィールドの場合は、一方を指定して追加したほうがいいです。両方とも記憶が混乱しやすくなります。一方のマッピングファイルのsetタグにinverse="true"を入れて制御権を他の方に処理してください。【inverse属性は一対の多双方向関連、多対多双方向関連にのみ適用可能】
Role.javaを変更:
 
 
package com.wyx.hibernate;

import java.util.Set;

public class Role {
	private int roleid;
	private String rolename;
	private Set users;
	getter & setter...
}
 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 package="com.wyx.hibernate">
	<class name="Role" table="t_Role">
		<id name="roleid">
			<generator class="native"/>
		</id>
		<property name="rolename"/>
		<set name="users" table="t_User_Role" inverse="true" cascade="all" order-by="userid">
			<key column="roleid"/>
			<many-to-many class="User" column="userid"/>
		</set>
	</class>
</hibernate-mapping>
                 /**
	 * save role casecad user
	 */
	public void testSave(){
		Session session = HibernateUtils.getSession();
		try {
			session.beginTransaction();
			
			User user1 =new User();
			user1.setUsername("  ");
			User user2 =new User();
			user2.setUsername("  ");
			Set users = new HashSet<User>();
			users.add(user1);
			users.add(user2);
			
			Role role = new Role();
			role.setRolename("   ");
			role.setUsers(users);
			session.save(role);
			
			session.getTransaction().commit();
		} catch (HibernateException e) {
			e.printStackTrace();
			session.getTransaction().rollback();
		}finally{
			HibernateUtils.closeSession(session);
		}
		
	}
   
inserse="true"を追加すると、Roleからデータを預け入れることはできません。上記のテスト方法でデータを保存します。中間表はデータを預け入れることはできませんが、inserseを削除すればいいです。エラーを防ぐために、やはりinverseを指定側から制御して追加したほうがいいです。