随笔-55  评论-208  文章-0  trackbacks-0
天花费了n久时间在一个hibernate的双键关联问题上好在最后问题还是解决了,不然我会睡不着觉的
问题:
我的数据库结构是这样的:

首先一开始我可以获得一个频道的channelId,我根据这个channelId得到一个首页区块的List,我在hibernate中配置homepagearea的加载方式,这样就可以通过homepage的到关联的栏目column(多对一关系),然后我还是使用hibernate的自动加载,取到column关联的专题subject(一对多关系)。
这时候问题出来了,由于column到subject的关联没有带channel信息,所以,我取到的subject实际上是一个column下所有的subject,而我期望的是要得到,一个homepagearea下根据channelId和columnId取得的subject.

解决思路:
希望通过hibernate直接建立homepage和subject的1对多关联关系

解决方法
首先我改变原来利用工具生成的hibernate配置文件和entitybean
先列出原来的homepagearea的配置文件
<?xml version="1.0"?>
<!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.easou.wapsearch.channel.entity.CsHomepageArea"
    table="CS_HOMEPAGE_AREA"
    schema="WAPUSER"
    lazy="true"
>
    <id
        name="id"
        type="long"
        column="ID"
        length="22"
    >
     <generator class="assigned">
      
     </generator>
    </id>
    <property
        name="createdBy"
        type="long"
        column="CREATED_BY"
        length="22"
    />
    <property
        name="createdDate"
        type="timestamp"
        column="CREATED_DATE"
        length="7"
    />
    <property
        name="isMore"
        type="long"
        column="IS_MORE"
        length="22"
    />
    <property
        name="name"
        type="string"
        column="NAME"
        length="50"
    />
    <property
        name="rowCount"
        type="long"
        column="ROW_COUNT"
        length="22"
    />
    <property
        name="showCount"
        type="long"
        column="SHOW_COUNT"
        length="22"
    />
    <property
        name="theOrder"
        type="long"
        column="THE_ORDER"
        length="22"
    />
    <property
        name="updateBy"
        type="long"
        column="UPDATE_BY"
        length="22"
    />
    <property
        name="updateDate"
        type="timestamp"
        column="UPDATE_DATE"
        length="7"
    />

    <!-- Associations -->
    <!-- bi-directional many-to-one association to CsChannel -->
    <many-to-one
        name="csChannel"       
    >
        <column name="CHANNEL_ID" length="22"/>
    </many-to-one>
    <!-- bi-directional many-to-one association to CsColumn -->
    <many-to-one
        name="csColumn"       
    >
        <column name="COLUMN_ID" length="22"/>
    </many-to-one>

</class>
</hibernate-mapping>

为了让homepagearea和subject形成一种一对多的关系,我增加的一个
<set name="csSubjects" inverse="true" cascade="save-update"
   lazy="false" order-by="THE_ORDER" table="CS_SUBJECT"
   outer-join="true">
   <key>
    <column name="CHANNEL_ID" index="CHANNEL_ID" />
    <column name="COLUMN_ID" index="COLUMN_ID" />
   </key>
   <one-to-many
    class="com.easou.wapsearch.channel.entity.CsSubject" />
</set>
但是由于hibernate一对多映射的一端必须是主键,而且我这里需要关联的还是2列信息,所以我还必须要修改配置文件的主键设置
<composite-id mapped="false" unsaved-value="none">
      <key-many-to-one name="csChannel" column="CHANNEL_ID"></key-many-to-one>
   <key-many-to-one name="csColumn" column="COLUMN_ID"></key-many-to-one>
</composite-id>
并且遮蔽掉原有的channel和column多对一关联关系,否则会报告重复错误
<!-- Associations
   bi-directional many-to-one association to CsChannel
  <many-to-one name="csChannel" lazy="true">
   <column name="CHANNEL_ID" length="22" />
  </many-to-one>
   bi-directional many-to-one association to CsColumn
  <many-to-one name="csColumn" lazy="true">
   <column name="COLUMN_ID" length="22" />
  </many-to-one>

  -->
这样hibernate才会在加载homepagearea时自动把subject的关联信息也加载进来了


最后的homepagearea配置文件
<?xml version="1.0"?>
<!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.easou.wapsearch.channel.entity.CsHomepageArea"
  table="CS_HOMEPAGE_AREA" schema="WAPUSER" lazy="true">
  <composite-id mapped="false" unsaved-value="none">
      <key-many-to-one name="csChannel" column="CHANNEL_ID"></key-many-to-one>
   <key-many-to-one name="csColumn" column="COLUMN_ID"></key-many-to-one>
  </composite-id>
  <property name="createdBy" type="long" column="CREATED_BY"
   length="22" />
  <property name="createdDate" type="timestamp"
   column="CREATED_DATE" length="7" />
  <property name="isMore" type="long" column="IS_MORE"
   length="22" />
  <property name="name" type="string" column="NAME" length="50" />
  <property name="rowCount" type="long" column="ROW_COUNT"
   length="22" />
  <property name="showCount" type="long" column="SHOW_COUNT"
   length="22" />
  <property name="theOrder" type="long" column="THE_ORDER"
   length="22" />
  <property name="updateBy" type="long" column="UPDATE_BY"
   length="22" />
  <property name="updateDate" type="timestamp"
   column="UPDATE_DATE" length="7" />

  <!-- Associations
   bi-directional many-to-one association to CsChannel
  <many-to-one name="csChannel" lazy="true">
   <column name="CHANNEL_ID" length="22" />
  </many-to-one>
   bi-directional many-to-one association to CsColumn
  <many-to-one name="csColumn" lazy="true">
   <column name="COLUMN_ID" length="22" />
  </many-to-one>

  -->
  <set name="csSubjects" inverse="true" cascade="save-update"
   lazy="false" order-by="THE_ORDER" table="CS_SUBJECT"
   outer-join="true">
   <key>
    <column name="CHANNEL_ID" index="CHANNEL_ID" />
    <column name="COLUMN_ID" index="COLUMN_ID" />
   </key>
   <one-to-many
    class="com.easou.wapsearch.channel.entity.CsSubject" />

  </set>


 </class>

</hibernate-mapping>

经验总结:
1、本来使用hibernate的加载策略就是为了把一些业务逻辑直接融合在数据库关系当中,但是由于自己逻辑没有考虑清楚造成了加载时信息的丢失(而且我觉得我的表结构有问题,不知有有没有dba给我指点一下问题)。
2、hibernate的一对多关联关系多端是1端是针对主键的,所以不论你是关联的是1列2列还是3列,它们都应该是你的1端的主键或者联合主键(其实一对一,多对一,多对多的原理也是相似的)。

参考资料:hibernate_reference(3.2)

posted on 2006-11-08 00:42 rocket 阅读(2519) 评论(0)  编辑  收藏

只有注册用户登录后才能发表评论。


网站导航: