Hibernate的多对多关联关系

假如一个公司的组织结构发展到一定阶段,原来所定义的一个用户只属于一个部门这种需求将会发生变化,一个用户(员工)可能担任多个角色,比如,一个员工可能既是人力资源部主管、又是财务部的总监,一个人属于多个部门是再正常不过的了!那此时,一个用户可以同时多个部门,一个部门下面又有多个员工,那员工与部门之间就是一种多对多关联关系。再如,用户跟角色之间的关联关系,一个用户他可能是属于系统管理员,也可能是属于某一个项目的项目经理,也可能他是信息发布管理员等,一个用户可以同时拥有多个角色。每个角色可以有多个用户,那用户跟角色之间是一种多对多的关联关系。
    下面,将以用户跟角色的关联关系来介绍一下多对多的关联关系。
    物理数据模型如下图所示:
略

从上图我们可以看出,对于建立多对多关联关系时,我们需要建立中间表,中间表是由一个USER_ID跟一个ROLE_ID组成一个联合组件。

建表的SQL:

程序代码
/*==============================================================*/
/* DBMS name:      MySQL 5.0                                    */
/* Created on:     2008-4-23 12:32:13                           */
/*==============================================================*/
drop table if exists T_ROLE ;

drop table if exists T_ROLE_USER ;

drop table if exists T_USER ;

/*==============================================================*/
/* Table: T_ROLE                                                */
/*==============================================================*/
create table T_ROLE
(
   ID                   int not null auto_increment ,
   ROLE_NAME            VARCHAR (20 ) not null ,
   DESCRIPTION          VARCHAR (255 ) ,
   primary key (ID )
) ;

/*==============================================================*/
/* Table: T_ROLE_USER                                           */
/*==============================================================*/
create table T_ROLE_USER
(
   USER_ID              INT not null ,
   ROLE_ID              INT not null ,
   primary key (USER_ID , ROLE_ID )
) ;

/*==============================================================*/
/* Table: T_USER                                                */
/*==============================================================*/
create table T_USER
(
   ID                   INT not null auto_increment ,
   USER_NAME            VARCHAR (20 ) not null ,
   LOGINID              VARCHAR (20 ) not null ,
   PASSWORD             VARCHAR (32 ) not null ,
   primary key (ID )
) ;

alter table T_ROLE_USER add constraint FK_Reference_1 foreign key (USER_ID )
      references T_USER (ID ) on delete restrict on update restrict ;

alter table T_ROLE_USER add constraint FK_Reference_2 foreign key (ROLE_ID )
      references T_ROLE (ID ) on delete restrict on update restrict ;



初始化数据:
 程序代码

insert into t_user (user_name ,loginId , password ) values ( '哲哲' , 'zizz' , 'admin' ) ;
insert into t_role (role_name ,description ) values ( '系统管理员' , '拥有系统的所有操作权限' ) ;



    对象模型如下图所示:

他们之间的关联关系为:用户对象有一个成员,成员类型是一个Set,该集合里面包含了用户所属的组。

User.java

程序代码
package zizz .model ;

import java .io .Serializable ;
import java .util .Set ;

/**
* 该对象是针对着数据库的T_USER表.
*
* <a href="http://www.suneca.com">ZIZZ</a>
*
* Create-Time:Apr 21, 2008 9:53:58 PM
*/

public class User implements Serializable {

     /**
     * serialVersionUID
     */

     private static final long serialVersionUID = 1L ;

     private int id ;
    
     private String userName ;
    
     private String loginId ;
    
     private String password ;
    
     private Set <Role > roles ;

     public int getId ( ) {
         return id ;
     }

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

     public String getUserName ( ) {
         return userName ;
     }

     public void setUserName (String userName ) {
         this .userName = userName ;
     }

     public String getLoginId ( ) {
         return loginId ;
     }

     public void setLoginId (String loginId ) {
         this .loginId = loginId ;
     }

     public String getPassword ( ) {
         return password ;
     }

     public void setPassword (String password ) {
         this .password = password ;
     }

     public Set <Role > getRoles ( ) {
         return roles ;
     }

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



User.hbm.xml

程序代码
< ?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 = "zizz.model" >
     < class name = "User" table = "T_USER" >
         <id name = "id" column = "ID" >
             <generator class = "increment" / >
         < /id >

         <property name = "userName" column = "USER_NAME" / >
         <property name = "loginId" column = "LOGINID" / >
         <property name = "password" column = "PASSWORD" / >      
        
         <set name = "roles" inverse = "false" cascade = "all" lazy = "true" table = "T_ROLE_USER" >
             <key column = "USER_ID" / >
             <many -to -many column = "ROLE_ID" class = "Role" / >
         < /set >
     < / class >
< /hibernate -mapping >



Role.java

程序代码
package zizz .model ;

import java .io .Serializable ;
import java .util .Set ;

/**
* 角色对象,该对象映射为数据库T_ROLE表.
*
* <a href="http://www.suneca.com">ZIZZ</a>
*
* Create-Time:Apr 23, 2008 4:19:31 PM
*/

public class Role implements Serializable {

     /**
     * serialVersionUID
     */

     private static final long serialVersionUID = 1L ;

     private int id ;
    
     private String roleName ;
    
     private String description ;
    
     private Set <User > users ;

     public int getId ( ) {
         return id ;
     }

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

     public String getRoleName ( ) {
         return roleName ;
     }

     public void setRoleName (String roleName ) {
         this .roleName = roleName ;
     }

     public String getDescription ( ) {
         return description ;
     }

     public void setDescription (String description ) {
         this .description = description ;
     }

     public Set <User > getUsers ( ) {
         return users ;
     }

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



Role.hbm.xml

程序代码
< ?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 = "zizz.model" >
     <class name = "Role" table = "T_ROLE" >
         <id name = "id" column = "ID" >
             <generator class = "increment" / >
         < /id >

         <property name = "roleName" column = "ROLE_NAME" / >
         <property name = "description" column = "DESCRIPTION" / >    
        
         <set name = "users" inverse = "false" cascade = "all" lazy = "true"  table = "T_ROLE_USER" >
             <key column = "ROLE_ID" / >
             <many-to-many column = "USER_ID" class = "User" / >
         < /set >          
     < /class >
< /hibernate-mapping >



假如我们的数据库T_USER表当中有一条数据,ID为1;T_ROLE当中有一条数据,ID也为1,现在我们想指派角色给用户,那我们可以使用以下的方式实现:
ManyToMany.java

程序代码
package zizz .test ;

import zizz .dao .RoleDAO ;
import zizz .dao .UserDAO ;
import zizz .dao .hibernate .RoleDAOHibernate ;
import zizz .dao .hibernate .UserDAOHibernate ;
import zizz .model .Role ;
import zizz .model .User ;

/**
* 测试多对多.
*
* <a href="http://www.suneca.com">ZIZZ</a>
*
* Create-Time:Apr 23, 2008 4:21:53 PM
*/

public class ManyToMany {
    
     public static void main (String [ ] args ) {
        ManyToMany .assignRoleToUser ( ) ;
     }
    
     public static void assignRoleToUser ( ) {
         /*因为插入T_USER、以及T_ROLE表第一条数据,id都为1*/
         /* 得到角色 */
        RoleDAO rdao = new RoleDAOHibernate ( ) ;
        Role role = rdao .findRoleById (1 ) ;
         /* 得到用户 */
        UserDAO udao = new UserDAOHibernate ( ) ;
        User user = udao .findUserById (1 ) ;
        
         /* 将角色指派给用户 */
        user .getRoles ( ) .add (role ) ;
        udao .updateUser (user ) ;
     }

}



系统控制台打印的SQL信息:

程序代码
Hibernate : select user0_ .ID as ID0_0_ , user0_ .USER_NAME as USER2_0_0_ , user0_ .LOGINID as LOGINID0_0_ , user0_ .PASSWORD as PASSWORD0_0_ from T_USER user0_ where user0_ .ID = ?
Hibernate : select roles0_ .USER_ID as USER1_1_ , roles0_ .ROLE_ID as ROLE2_1_ , role1_ .ID as ID2_0_ , role1_ .ROLE_NAME as ROLE2_2_0_ , role1_ .DESCRIPTION as DESCRIPT3_2_0_ from T_ROLE_USER roles0_ left outer join T_ROLE role1_ on roles0_ .ROLE_ID =role1_ .ID where roles0_ .USER_ID = ?
Hibernate : insert into T_ROLE_USER (USER_ID , ROLE_ID ) values ( ? , ? )



在维护多对多关联关系的时候,必须保证前后的SESSION是同一个,否则,将会出问题!将会抛出以下的错误信息:

程序代码
Exception in thread "main" org.hibernate.HibernateException: Illegal attempt to associate a collection with two open sessions
    at org.hibernate.collection.AbstractPersistentCollection.setCurrentSession(AbstractPersistentCollection.java:410)
    at org.hibernate.event.def.OnUpdateVisitor.processCollection(OnUpdateVisitor.java:40)
    at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:101)
    at org.hibernate.event.def.AbstractVisitor.processValue(AbstractVisitor.java:61)
    at org.hibernate.event.def.AbstractVisitor.processEntityPropertyValues(AbstractVisitor.java:55)
    at org.hibernate.event.def.AbstractVisitor.process(AbstractVisitor.java:123)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.performUpdate(DefaultSaveOrUpdateEventListener.java:267)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsDetached(DefaultSaveOrUpdateEventListener.java:216)
    at org.hibernate.event.def.DefaultUpdateEventListener.performSaveOrUpdate(DefaultUpdateEventListener.java:33)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
    at org.hibernate.impl.SessionImpl.fireUpdate(SessionImpl.java:559)
    at org.hibernate.impl.SessionImpl.update(SessionImpl.java:547)
    at org.hibernate.impl.SessionImpl.update(SessionImpl.java:539)
    at zizz.dao.hibernate.UserDAOHibernate.updateUser(UserDAOHibernate.java:53)
    at zizz.test.ManyToMany.assignRoleToUser(ManyToMany.java:34)
    at zizz.test.ManyToMany.main(ManyToMany.java:20)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值