Hibernate的单、双向关联(二)

来源:互联网 发布:apache设置虚拟路径 编辑:程序博客网 时间:2024/06/12 19:47
 

6.3  问题:在Hibernate中配置连接表

6.3.1  提出问题

设计师L在了解了连接表的优点之后,就将数据库中的一些必要的表-表关系设计成了连接表。程序员M使用Hibernate框架来完成开发时提出了问题:在Hibernate框架中如何配置连接表?配置的连接表对于具体持久化方法的调用会有什么影响?

6.3.2  在Hibernate中的连接表配置

首先看一个例子。Room实体与UserInfo实体是一对多关系,room2表与userinfo2表通过一张连接表来表现这层关系,连接表为roomusers。将来在连接表中可以出现room2表与userinfo2表的主键来维护关系。由于Room实体与UserInfo实体是一对多,因此在roomusers连接表中,userinfo2表的主键是惟一的。

针对这个例子,其在Hibernate中的映射文件将会如下配置,见例6.18。

例6.18:一对多连接表映射文件

Room2.hbm.xml(一端的配置)

<hibernate-mapping package="testhibernate">

     <class name="Room" table="room2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String"/>

          <property name="roomnumber" column="roomnumber" type="java.lang.String"/>

          <!-- 通过连接表的一端,因此需要table属性为roomusers -->

          <set name="users" cascade="all" table="roomusers">

               <!-- 该key的字段为连接表中的字段,作为外键 -->

               <key column="roomid"></key>

               <!-- 配置多对多 -->

               <!-- 但是unique属性为true,表示userid字段为不可重复,保证一对多关系  -->

               <many-to-many class="UserInfo" unique="true" column="userid"> </many-to-many>

               <!-- 在多对多中只要设置unique="true"即可以等同认为是一对多 -->

          </set>

     </class>

</hibernate-mapping>

UserInfo2.hbm.xml(多端的配置)

<hibernate-mapping package="testhibernate">

     <class name="UserInfo" table="userinfo2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String" not-null="true" />

          <property name="sex" column="SEX" type="java.lang.String" />

          <!-- 使用join来配置多对一的连接,以table属性来表示连接表的多对一,连接表为roomusers -->

          <!-- optional属性表示这是一个外连接,inverse属性可以出现在一端和多端,这里选择出现在多端,效果相同 -->

          <join table="roomusers" optional="true" inverse="true">

               <!-- 该key的字段为连接表中的字段,作为外键 -->

               <key column="userid" />

               <!-- 连接表中配置多对一,对应的字段为roomid -->

               <many-to-one name="room" column="roomid" not-null="true"/>

          </join>

     </class>

</hibernate-mapping>

与不使用连接表的一对多双向关联相比,使用连接表最大的不同如下:

一端:

(1)在<set>元素中需要增加table属性,以表示这是一个连接表的关系。

(2)将不使用连接表一对多的<one-to-many>改为<many-to-many>,并增加unique属性。

(3)在<set>元素中的所有字端都将针对连接表(table属性所指定的表)。

多端:

(1)使用<join>元素来配置多端的连接。

(2)在<join>元素中,所有字端都将针对连接表(table属性所指定的表)。

随后是针对连接表一对多的客户端的实现代码,该段代码与不使用连接表的一对多几乎一致,见例6.19。

例6.19:连接表一对多的操作

     public void run() {

          //创建Room实体

          Room room = new Room();

          //设置Room.name

          room.setName("rwhome");

          //设置Room.roomnumber

          room.setRoomnumber("001");

          //创建UserInfo实体

          UserInfo userInfo = new UserInfo();

          //设置UserInfo.name

          userInfo.setName("rw");

          //设置UserInfo.sex

          userInfo.setSex("M");

          //保证UserInfo实体得到与Room实体的关系,以帮助由连接表来维护一对多关联

          userInfo.setRoom(room);

          //创建UserInfo集合userInfoSet

          Set userInfoSet = new HashSet();

          //添加UserInfo实体到集合userInfoSet

          userInfoSet.add(userInfo);

          //设置Room.users(这是一个集合类型)

          room.setUsers(userInfoSet);

         

          //创建Hibernate Session

          Session session = HibernateSessionFactory.currentSession();

          //启动事务

          Transaction tx = session.beginTransaction();

          //持久化Room实体

          //此时将更新表room2和userinfo2以及维护关系的roomusers表

          ①session.save(room);    

          //提交事务

          tx.commit();

          //关闭Hibernate Session

          HibernateSessionFactory.closeSession();

          session = HibernateSessionFactory.currentSession();

          tx = session.beginTransaction();

          //获取Room实体以成为持久化状态,此时将获取room2表的所有字段信息

          //通过外连接roomusers获取userinfo2表的所有字段信息

          ②Room room1 = (Room)session.get(Room.class, room.getId());

          //删除room2表对应的userinfo2表以及连接表roomusers中的相关记录

          ③session.delete(room1);    

          tx.commit();

          HibernateSessionFactory.closeSession();

     }

针对该段代码的SQL语句如下:

Hibernate:

/* ①session.save(room)的动作,插入表room2 */

 insert

        into

            room2

            (NAME, roomnumber, id)

        values

            (?, ?, ?)

Hibernate:

/* ①session.save(room)的动作,插入表userinfo2 */

insert

        into

            userinfo2

            (NAME, SEX, id)

        values

            (?, ?, ?)

Hibernate:

/* ①session.save(room)的动作,插入表roomusers,维护关系*/

 insert

        into

            roomusers

            (roomid, userid)

        values

            (?, ?)

Hibernate:

/* ②Room room1 = (Room)session.get(Room.class, room.getId())的动作,获取room2表的信息 */

 select

        room0_.id as id2_0_,

        room0_.NAME as NAME2_0_,

        room0_.roomnumber as roomnumber2_0_

    from

        room2 room0_

    where

        room0_.id=?

Hibernate:

/*②Room room1 = (Room)session.get(Room.class, room.getId())的动作,通过连接表获取userinfo2表的信息*/

select

        users0_.roomid as roomid1_,

        users0_.userid as userid1_,

        userinfo1_.id as id0_0_,

        userinfo1_.NAME as NAME0_0_,

        userinfo1_.SEX as SEX0_0_,

        userinfo1_1_.roomid as roomid1_0_

    from

        roomusers users0_

    left outer join

        userinfo2 userinfo1_

            on users0_.userid=userinfo1_.id

    left outer join

        roomusers userinfo1_1_

            on userinfo1_.id=userinfo1_1_.userid

    where

        users0_.roomid=?

Hibernate:

/* ③session.delete(room1)的动作,删除roomusers连接表记录 */

delete

        from

            roomusers

        where

            roomid=?

Hibernate:

/* ③session.delete(room1)的动作,删除userinfo2表记录 */

delete

        from

            userinfo2

        where

            id=?

Hibernate:

/* ③session.delete(room1)的动作,删除room2表记录 */

delete

        from

            room2

        where

            id=?

可以看到,针对连接表的一对多关联,其操作在Hibernate中是连动3张表的。而且在获取实体时,将通过映射配置的optional属性来保证外连接的关系获取。

6.3.3  多对多连接表配置和实现

连接表的配置最常见的使用是维护多对多关系,假设Room实体和UserInfo实体是一个多对多关系,那么其映射配置见例6.20。

例6.20:维护Room实体和UserInfo实体多对多关系

Room2.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="testhibernate">

     <class name="Room" table="room2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String"/>

          <property name="roomnumber" column="roomnumber" type="java. lang.String"/>

          <!-- 通过连接表的多端,因此需要table属性为roomusers -->

          <set name="users" cascade="all" table="roomusers">

               <!-- 该key的字段为连接表中的字段,作为外键 -->

               <key column="roomid"></key>

               <!-- 连接表中配置多对多 -->

               <many-to-many class="UserInfo" column="userid"></many-to-many>

          </set>

     </class>

</hibernate-mapping>

UserInfo2.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="testhibernate">

     <class name="UserInfo" table="userinfo2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String" not-null="true" />

          <property name="sex" column="SEX" type="java.lang.String" />

          <!-- 通过连接表的多端,因此需要table属性为roomusers -->

          <set name="rooms" cascade="all" table="roomusers">

               <!-- 该key的字段为连接表中的字段,作为外键 -->

               <key column="userid"></key>

               <!-- 连接表中配置多对多 -->

               <many-to-many class="Room" column="roomid"></many-to-many>

          </set>

     </class>

</hibernate-mapping>

可以看到,在两个实体映射文件中都配置了many-to-many关系,这样的配置已经可以通过任意一个多端来维护另一端。实现持久化的代码见例6.21。

例6.21:实现持久化

     public void run() {

          //创建Room实体

          Room room = new Room();

          //设置Room.name

          room.setName("rwhome");

          //设置Room.roomnumber

          room.setRoomnumber("001");

          //创建第二个Room实体

          Room room2 = new Room();

          //设置Room.name

          room2.setName("rwhome2");

          //设置Room.roomnumber

          room2.setRoomnumber("002");

          //创建UserInfo实体

          UserInfo userInfo = new UserInfo();

          //设置UserInfo.name

          userInfo.setName("rw");

          //设置UserInfo.sex

          userInfo.setSex("M");

          //创建第二个UserInfo实体

          UserInfo userInfo2 = new UserInfo();

          //设置UserInfo.name

          userInfo2.setName("rw2");

          //设置UserInfo.sex

          userInfo2.setSex("M2");

          //创建第二个UserInfo实体与第二个Room实体的关系,通过连接表维护关系

          ①Set roomSet = new HashSet();

          roomSet.add(room2);

          userInfo2.setRooms(roomSet);

          //创建第一个Room实体与第一、第二个UserInfo实体的关系,通过连接表维护关系

          //添加UserInfo实体到集合userInfoSet

          ②Set userInfoSet = new HashSet();

          userInfoSet.add(userInfo);

          userInfoSet.add(userInfo2);

          room.setUsers(userInfoSet);

         

          //创建Hibernate Session

          Session session = HibernateSessionFactory.currentSession();

          //启动事务

          Transaction tx = session.beginTransaction();

          //持久化Room实体

          //此时将更新表room2和userinfo2以及维护关系的roomuser表

          ③session.save(room);    

          //提交事务

          tx.commit();

          //关闭Hibernate Session

          HibernateSessionFactory.closeSession();

         

          session = HibernateSessionFactory.currentSession();

          tx = session.beginTransaction();

          //获取Room实体以成为持久化状态,此时将获取room2表的所有字段信息

          ④Room roomF1 = (Room)session.get(Room.class, room.getId());

         

          //通过外连接roomusers获取userinfo2表的对应字段信息

          ⑤Iterator iF1 = roomF1.getUsers().iterator();

          while(iF1.hasNext()) {

               UserInfo userInfoF = (UserInfo)iF1.next();

               System.out.println(userInfoF.getId());

               System.out.println(userInfoF.getName());

               System.out.println(userInfoF.getSex());

          }

          //获取Room实体以成为持久化状态,此时将获取room2表的所有字段信息

          ⑥Room roomF2 = (Room)session.get(Room.class, room2.getId());

         

          //通过外连接roomusers获取userinfo2表的对应字段信息

          ⑦Iterator iF2 = roomF2.getUsers().iterator();

          while(iF2.hasNext()) {

               UserInfo userInfoF = (UserInfo)iF2.next();

               System.out.println(userInfoF.getId());

               System.out.println(userInfoF.getName());

               System.out.println(userInfoF.getSex());

          }

          tx.commit();

          HibernateSessionFactory.closeSession();

     }

针对该段代码的SQL语句如下:

Hibernate:

/* ③session.save(room)的动作,插入第一个Room实体 */

 insert

        into

            room2

            (NAME, roomnumber, id)

        values

            (?, ?, ?)

Hibernate:

/* ③session.save(room)的动作,通过②的动作,插入第二个UserInfo实体*/

insert

        into

            userinfo2

            (NAME, SEX, id)

        values

            (?, ?, ?)

Hibernate:

/* ③session.save(room)的动作,通过①的动作,插入第二个Room实体*/

insert

        into

            room2

            (NAME, roomnumber, id)

        values

            (?, ?, ?)

Hibernate:

/* ③session.save(room)的动作,通过②的动作,插入第一个UserInfo实体*/

insert

        into

            userinfo2

            (NAME, SEX, id)

        values

            (?, ?, ?)

Hibernate:

/* ③session.save(room)的动作,通过②的动作,维护第一个Room实体和第一个UserInfo实体关系*/

 insert

        into

            roomusers

            (roomid, userid)

        values

            (?, ?)

Hibernate:

/* ③session.save(room)的动作,通过②的动作,维护第一个Room实体和第二个UserInfo实体关系*/

 insert

        into

            roomusers

            (roomid, userid)

        values

            (?, ?)

Hibernate:

/* ③session.save(room)的动作,通过②的动作,维护第二个UserInfo实体和第一个Room实体关系*/

 insert

        into

            roomusers

            (userid, roomid)

        values

            (?, ?)

Hibernate:

/* ④Room roomF1 = (Room)session.get(Room.class, room.getId())的动作,获取第一个Room实体 */

select

        room0_.id as id2_0_,

        room0_.NAME as NAME2_0_,

        room0_.roomnumber as roomnumber2_0_

    from

        room2 room0_

    where

        room0_.id=?

Hibernate:

/* ⑤Iterator iF1 = roomF1.getUsers().iterator()的动作,通过连接表获取多个UserInfo实体,在本实现中对应将获取两条UserInfo实体记录 */

 select

        users0_.roomid as roomid1_,

        users0_.userid as userid1_,

        userinfo1_.id as id0_0_,

        userinfo1_.NAME as NAME0_0_,

        userinfo1_.SEX as SEX0_0_

    from

        roomusers users0_

    left outer join

        userinfo2 userinfo1_

            on users0_.userid=userinfo1_.id

    where

        users0_.roomid=?

Hibernate:

/* ⑥Room roomF2 = (Room)session.get(Room.class, room2.getId())的动作,获取第二个Room实体 */

select

        room0_.id as id2_0_,

        room0_.NAME as NAME2_0_,

        room0_.roomnumber as roomnumber2_0_

    from

        room2 room0_

    where

        room0_.id=?

Hibernate:

/* ⑦Iterator iF2 = roomF2.getUsers().iterator()的动作,通过连接表获取多个UserInfo实体,在本实现中对应只会获取一条UserInfo实体记录 */

select

        users0_.roomid as roomid1_,

        users0_.userid as userid1_,

        userinfo1_.id as id0_0_,

        userinfo1_.NAME as NAME0_0_,

        userinfo1_.SEX as SEX0_0_

    from

        roomusers users0_

    left outer join

        userinfo2 userinfo1_

            on users0_.userid=userinfo1_.id

    where

        users0_.roomid=?

通过本实现可以看到,对于多对多关系的维护在任意一个多端都可以进行。对于持久化方式的实现,不用考虑连接表,只对实体进行关系的维护可以直接影响连接表。

6.3.4  其他通过连接表的映射配置

在之前的小节中已经给出了一对多/多对一、多对多的两种映射配置和持久化实现。其实在Hibernate中,还支持更多的连接表关系映射。这里作一个总结并给出映射配置。

(1)一对多单向映射配置:与一对多/多对一双向关系配置类似,只是在多端不需要使用join元素来配置与一端的关联,见例6.22。

例6.22:连接表单向一对多的映射文件

Room2.hbm.xml(一端的配置)

<hibernate-mapping package="testhibernate">

     <class name="Room" table="room2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String"/>

          <property name="roomnumber" column="roomnumber" type="java. lang.String"/>

          <!-- 通过连接表的一端,因此需要table属性为roomusers -->

          <set name="users" cascade="all" table="roomusers">

               <!-- 该key的字段为连接表中的字段,作为外键 -->

               <key column="roomid"></key>

               <!-- 配置多对多 -->

               <!-- 但是unique属性为true,表示userid字段为不可重复,保证一对多关系  -->

               <many-to-many class="UserInfo" unique="true" column="userid"> </many-to-many>

               <!-- 在多对多中只要设置unique="true"即可以等同认为是一对多 -->

          </set>

     </class>

</hibernate-mapping>

UserInfo2.hbm.xml(多端的配置)

<hibernate-mapping package="testhibernate">

     <class name="UserInfo" table="userinfo2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String" not-null="true" />

          <property name="sex" column="SEX" type="java.lang.String" />

     </class>

</hibernate-mapping>

连接表的单向一对多关系只能通过一端来维护关系,而在抓取信息时,通过多端是无法抓取到一端信息的。在通过一端抓取多端记录时,将会执行外连接语句的SQL。连接表的单向一对多比非连接表的单向一对多建模语义要清晰得多,在效率上也不低,因此非常常见。

(2)多对一单向映射配置。与一对多/多对一双向关系配置类似,只是在一端不需要使用set元素来配置与多端的关联,见例6.23。

例6.23:连接表单向多对一的映射文件

Room2.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="testhibernate">

     <class name="Room" table="room2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String"/>

          <property name="roomnumber" column="roomnumber" type="java. lang.String"/>

     </class>

</hibernate-mapping>

UserInfo2.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="testhibernate">

     <class name="UserInfo" table="userinfo2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String" not-null="true" />

          <property name="sex" column="SEX" type="java.lang.String" />

          <!-- 使用join来配置多对一的连接,以table属性来表示连接表的多对一,连接表为roomusers -->

          <!-- optional属性表示这是一个外连接 -->

          <join table="roomusers" optional="true">

               <!-- 该key的字段为连接表中的字段,作为外键 -->

               <key column="userid" />

               <!-- 连接表中配置多对一,对应的字段为roomid -->

               <many-to-one name="room" class="Room" column="roomid" not-null="true"/>

          </join>

     </class>

</hibernate-mapping>

使用连接表的单向多对一关系是非常常见的,在通过多端抓取一端记录时,仅通过外连接连接表获取一端的主键或实体。

(3)连接表的单向一对一关系并不常见,只需在单向一对多的一端映射配置中设置属性unique即可,这里不做具体介绍。

(4)连接表的单向多对多关系也并不常见,这里仅给出其映射配置,见例6.24。

例6.24:连接表的单向多对多映射

Room2.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="testhibernate">

     <class name="Room" table="room2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String"/>

          <property name="roomnumber" column="roomnumber" type="java. lang.String"/>

          <!-- 通过连接表的多端,因此需要table属性为roomusers -->

          <set name="users" cascade="all" table="roomusers">

               <!-- 该key的字段为连接表中的字段,作为外键 -->

               <key column="roomid"></key>

               <!-- 连接表中配置多对多 -->

               <many-to-many class="UserInfo" column="userid"></many-to-many>

          </set>

     </class>

</hibernate-mapping>

UserInfo2.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="testhibernate">

     <class name="UserInfo" table="userinfo2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String" not-null="true" />

          <property name="sex" column="SEX" type="java.lang.String" />

     </class>

</hibernate-mapping>

(5)连接表的双向一对一关系并不常见,其配置映射需要在两端都配置<join>元素,见例6.25。

例6.25:连接表的双向一对一映射配置

Room2.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="testhibernate">

     <class name="Room" table="room2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String"/>

          <property name="roomnumber" column="roomnumber" type="java. lang.String"/>

          <!-- 使用join来配置一对一的连接,以table属性来表示连接表的一对一,连接表为roomusers -->

          <!-- optional属性表示这是一个外连接 -->

          <join table="roomusers" optional="true">

               <!-- 该key的字段为连接表中的字段,作为外键 -->

               <key column="roomid" unique="true"/>

               <!-- 连接表中配置一对一,对应的字段为roomid -->

               <many-to-one name="user" class="UserInfo" column="userid" not-null=" true" unique="true"/>

          </join>

     </class>

</hibernate-mapping>

UserInfo2.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="testhibernate">

     <class name="UserInfo" table="userinfo2">

          <id name="id" column="id" type="java.lang.Long">

               <generator class="increment" />

          </id>

          <property name="name" column="NAME" type="java.lang.String" not-null=" true" />

          <property name="sex" column="SEX" type="java.lang.String" />

          <!-- 使用join来配置一对一的连接,以table属性来表示连接表的一对一,连接表为roomusers -->

          <!-- optional属性表示这是一个外连接 -->

          <join table="roomusers" optional="true">

               <!-- 该key的字段为连接表中的字段,作为外键 -->

               <key column="userid" unique="true"/>

               <!-- 连接表中配置一对一,对应的字段为roomid -->

               <many-to-one name="room" class="Room" column="roomid" not-null="true"  unique="true"/>

          </join>

     </class>

</hibernate-mapping>

通过连接表来实现双向一对一关联并不是一个好办法,虽然Hibernate提供了这种方式,但是并不推荐使用。

6.3.5  结语

在Hibernate中提供了多种连接表关系映射的配置方案。其持久化实现并不用关心连接表,而是直接关注当前的实体,而框架在后台会根据配置自行对连接表进行维护来保证关系。因此在一定的条件下使用连接表的关系映射是非常有帮助的。下面是各种关系的一种比较。

1.实体一对多关系

(1)更新(获取)一端时同时更新(获取)多端,业务要求只通过一端来维护关系,使用双向一对多、单向一对多、连接表双向一对多、连接表单向一对多都可以,推荐使用双向一对多、连接表单向一对多。

(2)更新(获取)一端时同时更新(获取)多端,业务要求通过一端和多端都可维护关系,使用双向一对多、连接表双向一对多都可以,确定业务推荐双向一对多;扩展业务推荐连接表双向一对多。

2.实体多对多关系

(1)更新(获取)多端时同时更新(获取)另一多端,业务要求只通过一个多端来维护关系,使用连接表双向多对多、连接表单向多对多都可以,推荐使用连接表单向多对多。

(2)更新(获取)多端时同时更新(获取)另一多端,业务要求两个多端都可以维护关系,只能使用连接表双向多对多。

3.实体一对一关系

(1)更新(获取)一端时同时更新(获取)另一端,业务要求只通过一个一端来维护关系,使用双向一对一、单向一对一、连接表双向一对一、连接表单向一对一都可以,推荐使用单向一对一。

(2)更新(获取)一端时同时更新(获取)另一一端,业务要求两个一端都可维护关系,使用双向一对一、连接表双向一对一都可以,推荐使用双向一对一。

 

此书名:《揭密J2EE项目开发的70个问题

以上内容摘自http://book.csdn.net/bookfiles/563/10056318683.shtml

原创粉丝点击