关联关系"/>
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_role (role_name ,description ) values ( '系统管理员' , '拥有系统的所有操作权限' ) ;
对象模型如下图所示:
略
他们之间的关联关系为:用户对象有一个成员,成员类型是一个Set,该集合里面包含了用户所属的组。
User.java
import java .io .Serializable ;
import java .util .Set ;
/**
* 该对象是针对着数据库的T_USER表.
*
* <a href="">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
< !DOCTYPE hibernate -mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
".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
import java .io .Serializable ;
import java .util .Set ;
/**
* 角色对象,该对象映射为数据库T_ROLE表.
*
* <a href="">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
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
".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
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="">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 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是同一个,否则,将会出问题!将会抛出以下的错误信息:
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)
更多推荐
Hibernate的多对多关联关系
发布评论