Hibernate映射详解(五)--多对多关联映射 .

        举个例子来说,就是用户与角色。一个用户可以属于多个角色,而一个角色又可以拥有多个用户。文字表述就是这样了,看一下用图的直观表示。

实体关系图

 

表格关系图

        当关系两方有一端为一时,我们让多的一端维护关系,可以减少数据的冗余,提高效率。那要是多对多的话,如果还在某一方维护数据,那缺点就一点都没有避免。那怎么解决这个问题呢?我们呢采用第三张表格来维护这个关系。即上图中间用户角色表。将关系两方的主键抽离出来放到第三张表中。最大程度的减少冗余性。看一下具体实现。

实体类实现:

publicclass User {

   

    privateintid;

   

    private Stringname;

 

    privateSetroles; //关联属性

     省略getset方法

}

publicclass Role {

 

    privateintid;

   

    private Stringname;

     …省略getset方法

}

 

对应的映射文件实现

user.hbm.xml

<hibernate-mapping>

    <classname="com.bjpowernode.hibernate.User"table="t_user">

        <idname="id">

            <generatorclass="native"/>

        </id>

        <propertyname="name"/>

        <!--下面这段配置实现了生成第三张表,将user主键与role主键关联起来 -->

        <setname="roles"table="t_user_role">

           <keycolumn="user_id"/>

           <many-to-manyclass="com.bjpowernode.hibernate.Role"column="role_id"/>   

       </set>

    </class>

</hibernate-mapping>

Role.hbm.xml

<hibernate-mapping>

    <classname="com.bjpowernode.hibernate.Role"table="t_role">

        <idname="id">

            <generatorclass="native"/>

        </id>

        <propertyname="name"/>

    </class>

</hibernate-mapping>

 

 

 

 

看完单向,与前面一样,我们看一下双向。

实体类代码实现

public class User {

   

    privateintid;

   

    private Stringname;

 

    privateSetroles//关联属性

    省略getset方法

}

public class Role {

 

    privateintid;

   

    private Stringname;

   

    privateSet users; //关联属性

     省略getset方法

}

对应的配置文件的实现:

<hibernate-mapping>

    <classname="com.bjpowernode.hibernate.User"table="t_user">

        <idname="id">

            <generatorclass="native"/>

        </id>

        <propertyname="name"/>

       <setname="roles"table="t_user_role">

           <keycolumn="user_id"not-null="true"/>

           <many-to-manyclass="com.bjpowernode.hibernate.Role"column="role_id"/>   

       </set>

    </class>

</hibernate-mapping>

<hibernate-mapping>

    <classname="com.bjpowernode.hibernate.Role"table="t_role">

        <idname="id">

            <generatorclass="native"/>

        </id>

        <propertyname="name"/>

       <setname="users"table="t_user_role">

           <keycolumn="role_id"not-null="true"/>

           <many-to-manyclass="com.bjpowernode.hibernate.User"column="user_id"/>

       </set>

    </class>

</hibernate-mapping>

        多对多双向关联的实现原理也是新增一张表,使两端的主键联系起来。所以,在映射文件的配置时,生成的中间表名称必须是一样的,比如这里的set标签中定义的table字段t_user_role。除了表名称以外,表字段名称也必须是一样的如此处set标签中的column标签的值。

        到现在,关联映射我们就已经介绍完了。通过,这么多映射的比较,他们之间确实是有几点共性的地方。

        假设有关系A,B两端。若A与B有单向关联,即A—>B,则A的实体类中会有B作为他的属性。若B端为一(非多),则A中多一个B类型的属性,若B端为多,则A中多一个Set类型的集合,而它存储的类型当然为B。这跟A端是多或者一是没有关系的。那映射文件呢?若one-to-one或者many-to-one,one端name为另一端实体类中实例化的变量的名字。而若是*-to-many,则many一端name为多的一端的对象类所在的位置。哪个包下边哪个类。若实体中出现了Set类型的属性,那映射文件中对应的也会有Set标签。

posted @ 2012-05-25 12:40  转航  阅读(170)  评论(0编辑  收藏  举报