多对多实体映射
假设现在有User与Server两个类,一个User可以被授权使用多台Server,而在Server上也记录授权使用它的使用者,就User与Server两者而言即使多对多的关系。
在程序设计时,基本上是不建议直接在User与Server之间建立多对多关系,这会使得User与Server相互依赖,通常会通过一个中介类来维护两者之间的多对多关系,避免两者的相互依赖。
如果一定要直接建立User与Server之间的多对多关系,Hibernate也是支援的,基本上只要您了解之前介绍的几个实体映射,建立多对多关联在配置上并不困难。
先看一下我们设计的User与Server类:
代码:
1 User.java 2 package com; 3 import java.util.*; 4 public class User { 5 private long id; 6 private String name; 7 private Set servers = new HashSet(); 8 } 9 代码: Server.java 10 package com; 11 import java.util.*; 12 public class Server { 13 private long id; 14 private String address; 15 private Set users = new HashSet(); 16 }
这儿各使用HashSet来保存彼此的关系,在多对多关系映射上,我们可以建立单向或双向关系,这儿直接介绍双向关系映射,并藉由设定inverse="true",将关系的维护交由其中一方来维护,这么作的结果,在原始码的撰写上,也比较符合Java的对象关系维护,也就是双方都要设置至对方的参考。
首先来看看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> <class name="com.User" table="USER"> <id name="id" column="USER_ID" unsaved-value="0"> <generator class="increment"/> </id> <property name="name"> <column name="NAME" length="16" not-null="true"/> </property> <set name="servers" table="USER_SERVER" cascade="save-update"> <key column="USER_ID"/> <many-to-many class="com.Server" column="SERVER_ID"/> </set> </class> </hibernate-mapping>
在数据库中,数据表之间的多对多关系是通过一个中介的数据表来完成,例如在这个例子中,USER数据表与USER_SERVER数据表是一对多,而USER_SERVER对SERVER是多对一,从而完成USER至SERVER的多对多关系,在USER_SERVER数据表中,将会有USER_ID与SERVER_ID共同作为主键,USER_ID作为一个至USER的外键参考,而SERVER_ID作为一个至SERVER的外键参考。
来看看Server.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> <class name="com.Server" table="SERVER"> <id name="id" column="SERVER_ID" unsaved-value="0"> <generator class="increment"/> </id> <property name="address" type="string"/> <set name="users" table="USER_SERVER" inverse="true" cascade="save-update"> <key column="SERVER_ID"/> <many-to-many class="com.User" column="USER_ID"/> </set> </class> </hibernate-mapping>
设置上与User.hbm.xml是类似的,只是增加了inverse="true",表示将关系的维护交由另一端,注意我们在User与Server的cascade都是设置为save-update,在多对多的关系中,all、delete等cascade是没有意义的,因为多对多中,并不能因为父对象被删除,而造成被包括的子对象被删除,因为可能还有其它的父对象参考至这个子对象。
完!