2014年1月14日 星期二

雙向多對多 XML Mapping

在多對多的配置中,

會採用一個中介表來記錄對應的資料,

最常見的就是使用者(User)與角色(Role)的多對多配置,

一個User可以有很多種Role,

一個Role也對應很多個User,

可參考下圖:













透過一個user_role表來記錄兩個表格的多對多配置,

User.java
package com.model;

import java.util.Set;

public class User {
 private int id;
 private String name;
 private Set roles;

 public int getId() {
  return id;
 }

 public void setId(int id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public Set getRoles() {
  return roles;
 }

 public void setRoles(Set roles) {
  this.roles = roles;
 }
}

Role.java
package com.model;

import java.util.Set;

public class Role {
 private String id;
 private String name;
 private Set users;

 public String getId() {
  return id;
 }

 public void setId(String id) {
  this.id = id;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public Set getUsers() {
  return users;
 }

 public void setUsers(Set users) {
  this.users = users;
 }
}

皆透過set集合紀錄對應的多方

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>
 <class name="com.model.User" table="user">
  <id name="id">
   <generator class="native" />
  </id>
  <property name="name" type="string">
   <column name="name" length="10" not-null="true" />
  </property>
  <set name="roles" table="user_role" cascade="save-update">
   <key column="user_id" />
   <many-to-many class="com.model.Role" column="role_id" />
  </set>
 </class>
</hibernate-mapping>

由於多對多不會因為一方的資料刪除,

另一方也需要跟著刪除(還有其他資料對應),

所以cascade設定為save-update,

set內的key-column是指table user裡的id對應到table user-role內user的欄位名稱,

使用many-to-many的標籤,

對應Role物件,以及column對應的也是table user-role內role的欄位名稱,

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="com.model.Role" table="role">
  <id name="id" type="java.lang.String">
   <generator class="assigned" />
  </id>
  <property name="name" type="string">
   <column name="name" length="10" not-null="true" />
  </property>
  <set name="users" table="user_role" cascade="save-update" inverse="true">
   <key column="role_id" />
   <many-to-many class="com.model.User" column="user_id" />
  </set>
 </class>
</hibernate-mapping>

Role的部分配置inverse為true,

把控制權交給User,

這邊考慮的是由User做改變的機會比較多,

當然也可以把User的inverse設定為true,

把控制權改成在Role,

接下來是測試程式:

TestUserRole.java
package com.hibernate;

import java.util.HashSet;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.hibernate.util.HibernateUtils;
import com.model.Role;
import com.model.User;

public class TestUserRole {

 public static void main(String[] args) {

  Session session = HibernateUtils.getSessionFactory().openSession();
  Transaction tx = session.beginTransaction();
  try {
   User user_1 = new User();
   user_1.setName("Gary");
   user_1.setRoles(new HashSet());

   User user_2 = new User();
   user_2.setName("Peter");
   user_2.setRoles(new HashSet());

   Role role_manager = new Role();
   role_manager.setId("manager");
   role_manager.setName("系統管理者");
   role_manager.setUsers(new HashSet());

   Role role_employee = new Role();
   role_employee.setId("employee");
   role_employee.setName("一般員工");
   role_employee.setUsers(new HashSet());

   Role role_account = new Role();
   role_account.setId("account");
   role_account.setName("會計人員");
   role_account.setUsers(new HashSet());

   user_1.getRoles().add(role_manager);
   user_1.getRoles().add(role_employee);

   user_2.getRoles().add(role_manager);
   user_2.getRoles().add(role_account);

   session.save(user_1);
   session.save(user_2);

   tx.commit();
  } catch (Exception e) {
   tx.rollback();
   e.printStackTrace();
  } finally {
   session.close();
   HibernateUtils.shutdown();
  }
 }

}

執行的console畫面:

Hibernate: insert into user (name) values (?)
Hibernate: select role_.id, role_.name as name10_ from role role_ where role_.id=?
Hibernate: insert into role (name, id) values (?, ?)
Hibernate: insert into user (name) values (?)
Hibernate: select role_.id, role_.name as name10_ from role role_ where role_.id=?
Hibernate: select role_.id, role_.name as name10_ from role role_ where role_.id=?
Hibernate: insert into role (name, id) values (?, ?)
Hibernate: insert into role (name, id) values (?, ?)
Hibernate: insert into user_role (user_id, role_id) values (?, ?)
Hibernate: insert into user_role (user_id, role_id) values (?, ?)
Hibernate: insert into user_role (user_id, role_id) values (?, ?)
Hibernate: insert into user_role (user_id, role_id) values (?, ?)


table user















table role

















table user_role






沒有留言:

張貼留言