-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 
Author Message
 Post subject: many-to-many using an association class and composite ids
PostPosted: Thu Jan 08, 2009 5:03 pm 
Newbie

Joined: Thu Jan 08, 2009 3:48 pm
Posts: 3
Location: San Francisco
I'm having trouble using Hibernate 3.3.1 to implement a many-to-many association using an association class and composite keys, so I'm putting this out to the community in order to gain feedback on what I'm doing wrong in terms of design and/or Hibernate usage.

Background to the problem:
I'm building an open source project that implements a service for common collective intelligence tasks for a Web application, such as building a tag cloud from user tags, collaborative filtering, and clustering (e.g. k-Means). One of the goals of my project is to support a multi-tenant, shared schema deployment model, such as the one described at:
http://www.oracle.com/technology/tech/saas/pdf/saas-data-architecture-whitepaper.pdf

Consequently, this means I'll have composite keys. Here is the simplified ER diagram of my database, which I'm definitely willing to change in order to use Hibernate (admittedly, I'm not a very good relational database designer).

http://docs.google.com/Doc?id=dj52w55_0w2p6sbfd

I'm having trouble using Hibernate 3.3.1 to implement the many-to-many association between Users and Items. My current design uses a class named "UserItemIx" which encapsulates all the possible interactions between a User and an Item, such as:
+ User rating an Item
+ User viewing an Item one or more times
+ User marking an Item as a favorite
+ many more interactions I'd like to support, such as User adding a Tag to an Item

Here are the hbm declarations I'm using (based on the example in the Hibernate doc: 23.4.3. Many-to-many with shared composite key attribute)

Code:
  <class name="User" table="ciobjx_user">
    <composite-id name="id" class="ID">
      <key-property name="tenantId" column="tenant_id"/>
      <key-property name="objectId" column="object_id"/>
    </composite-id>
    <natural-id mutable="true">
      <property name="userId" column="user_id" length="60"/>
    </natural-id>
    <version name="version" column="version"/>
    <property name="lastName" column="last_name" length="60" not-null="true"/>
    <property name="language" column="language" length="10" not-null="true"/>
    <property name="isActive" column="is_active" type="boolean" not-null="true"/>
    <property name="createdOn" column="created_on" type="long" not-null="true"/>
    <property name="firstName" column="first_name" length="60" not-null="false"/>
    <property name="middleName" column="middle_name" length="60" not-null="false"/>
    <property name="email" column="email" length="90" not-null="false"/>
    <set name="userItems" table="ciobjx_user_item">
      <key>
        <column name="user_id"/>
        <column name="tenant_id"/>
      </key>
     <many-to-many class="UserItemIx">
        <column name="item_id"/>
        <formula>tenant_id</formula>
     </many-to-many>
    </set>
  </class>

  <class name="URLItem" table="ciobjx_item">
    <composite-id name="id" class="ID">
      <key-property name="tenantId" column="tenant_id"/>
      <key-property name="objectId" column="object_id"/>
    </composite-id>
    <natural-id mutable="true">
      <property name="uri" column="uri" length="255"/>
    </natural-id>
    <version name="version" column="version"/>
    <property name="mimeType" column="mimetype" length="60" not-null="true"/>
    <property name="language" column="language" length="3" not-null="true"/>
    <property name="createdBy" column="created_by" length="60" not-null="true"/>
    <property name="createdOn" column="created_on" type="long" not-null="true"/>
    <property name="type" column="type" length="60" not-null="true"/>
    <property name="title" column="title" length="255" not-null="true"/>
    <property name="isCacheable" column="is_cacheable" type="boolean" not-null="true"/>
    <property name="isUpdatable" column="is_updatable" type="boolean" not-null="true"/>
    <property name="timeToLive" column="time_to_live" type="long" not-null="true"/>
    <property name="encoding" column="encoding" length="60" not-null="false"/>
    <set name="userItems" table="ciobjx_user_item" inverse="true">
      <key>
        <column name="item_id"/>
        <column name="tenant_id"/>
      </key>
     <many-to-many class="UserItemIx">
        <column name="user_id"/>
        <formula>tenant_id</formula>
     </many-to-many>
    </set>
  </class>

  <class name="UserItemIx" table="ciobjx_user_item">
    <composite-id name="id" class="UserItemID">
      <key-property name="tenantId" column="tenant_id"/>
      <key-property name="userId" column="user_id"/>
      <key-property name="itemId" column="item_id"/>
    </composite-id>
    <many-to-one name="user" class="User" insert="false" update="false">
      <column name="tenant_id"/>
      <column name="user_id"/>
    </many-to-one>
    <many-to-one name="item" class="URLItem" insert="false" update="false">
      <column name="tenant_id"/>
      <column name="item_id"/>
    </many-to-one>
    <component name="rating" class="Rating" lazy="true">
      <property name="ratedOn" column="rated_on" not-null="false"/>
      <property name="rating" column="rating" not-null="false"/>
    </component>
    <property name="isFavorite" column="is_favorite" not-null="false"/>
    <set name="views" table="ciobjx_user_item_view">
      <key>
        <column name="tenant_id"/>
        <column name="user_id"/>
        <column name="item_id"/>
      </key>
      <composite-element class="View">
        <property name="occurredAt" column="viewed_on"/>
        <property name="referrer" column="referrer"/>
      </composite-element>
    </set>
  </class>


When I run my unit test, I get:

Code:
Caused by: org.hibernate.MappingException: collection element mapping has wrong number of columns: net.ciobjx.URLItem.userItems type: net.ciobjx.UserItemIx
at org.hibernate.mapping.Collection.validate(Collection.java:302)
at org.hibernate.mapping.Set.validate(Set.java:42)
at org.hibernate.cfg.Configuration.validate(Configuration.java:1139)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1320)


I've even tried just mapping UserItemIx as:

Code:
  <class name="UserItemIx" table="ciobjx_user_item">
    <composite-id name="id" class="UserItemID">
      <key-property name="tenantId" column="tenant_id"/>
      <key-property name="userId" column="user_id"/>
      <key-property name="itemId" column="item_id"/>
    </composite-id>
  </class>


Received the same error.

Can anyone shed some light on what may be wrong with my configuration or database design?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 1 post ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.