-->
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.  [ 5 posts ] 
Author Message
 Post subject: Help with a legacy mapping
PostPosted: Wed Nov 23, 2005 12:15 pm 
Newbie

Joined: Wed Nov 23, 2005 11:37 am
Posts: 9
Hi all. I'm getting my feet wet with Hibernate and have a tricky legacy database mapping that I need some help with.

I have two tables in a Parent/Children like relationship: a "registration" (think of this as a representation of the current state of a registration) and an associated "history" of the states that a registration has gone through. The problem seems to be that the primary key in the Registration table is a composite id, and the primary key in the RegistrationHistory table is a sequence generated id (i.e. single column) to allow for multiple history entries for a given registration.

Assume the tables are defined as follows:

Code:
Registration
------------------
identifier (PK)
source    (PK)
current_state


RegistrationHistory
----------------------
history_id (PK)
identifier (FK)
source (FK)
old_state
new_state



I have tried several mappings with no luck. Here's my current incarnation:

Code:
Registration
--------------

<?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="RegistrationDTO" table="Registration">
         <composite-id>
             <key-property name="identifier" column="identifier"/>
             <key-property name="source" column="source"/>
         </composite-id>
         <property name="currentState" column="current_state"/>

        <!-- registration history set mapping-->
        <set name="registrationHistory" cascade="all" lazy="true" order-by="history_id asc">
            <key>
                <column name="identifier" not-null="true"/>
                <column name="source" not-null="true"/>
            </key>
            <one-to-many class="RegistrationHistoryDTO"/>
        </set>
    </class>
</hibernate-mapping>


RegistrationHistory
----------------------

<?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="RegistrationHistoryDTO" table="RegistrationHistory">
         <id name="historyID" column="history_id">
             <generator class="sequence">
                 <param name="sequence">seq_hist_id</param>
             </generator>
         </id>
         <property name="identifier" column="identifier" not-null="true"/>
         <property name="source" column="data_source_id" not-null="true"/>
         <property name="oldState" column="old_state"/>
         <property name="newState" column="new_state"/>
     </class>
</hibernate-mapping>


I get the following mapping exception:

org.hibernate.MappingException: Repeated column in mapping for entity: RegistrationDTO column: identifier (should be mapped with insert="false" update="false")

I want each RegistrationDTO to have a property that is Set of RegistrationHistoryDTO objects (i.e. a one-to-many relationship). It seems to be indicating that I'm mapping the same column twice. But in all of the documentation examples, this is done repeatedly for simple single column ids. When you try to do this with composite-ids Hibernate seems to have a problem with it.

Obviously I'm doing something wrong. Any help/clues would be greatly appreciated. Thanks in advance!


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 23, 2005 12:46 pm 
Regular
Regular

Joined: Sat Nov 05, 2005 5:33 am
Posts: 70
Location: Linz, Austria
If I'm reading the example 8.2.3. one to many corretly, you don't have to (and maybe must not) define the properties of the foreign key in the detail class mapping.

Perhaps it helps,
Heinz
----------------------------
Don't forget to rate if this helped.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Nov 23, 2005 1:09 pm 
Newbie

Joined: Wed Nov 23, 2005 11:37 am
Posts: 9
Yeah, that section does seem to imply that, but the error indicates it's an error in the mapping file for Registration, not the RegistrationHistory.

Specifically, I think that the sections in bold below are most likely the culprit:

<hibernate-mapping>

<class name="RegistrationDTO" table="Registration">

<composite-id>
<key-property name="identifier" column="identifier"/>
<key-property name="source" column="source"/>
</composite-id>

<property name="currentState" column="current_state"/>

<!-- registration history set mapping-->
<set name="registrationHistory" cascade="all" lazy="true" order-by="history_id asc">

<key>
<column name="identifier" not-null="true"/>
<column name="source" not-null="true"/>
</key>

<one-to-many class="RegistrationHistoryDTO"/>
</set>
</class>
</hibernate-mapping>


Top
 Profile  
 
 Post subject:
PostPosted: Thu Nov 24, 2005 10:01 am 
Regular
Regular

Joined: Sat Nov 05, 2005 5:33 am
Posts: 70
Location: Linz, Austria
I'm stumped.

According to my experience, the key elements of a set definition refer to the associated class.


Have you tried removing the properties from the other class?

Regards,
Heinz


Top
 Profile  
 
 Post subject:
PostPosted: Mon Nov 28, 2005 2:07 pm 
Newbie

Joined: Wed Nov 23, 2005 11:37 am
Posts: 9
FYI, we finally figured out how to do this mapping. Here's how you do it:

Registration

Code:
<?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="RegistrationDTO" table="Registration">
         <composite-id name="registrationKey" class="RegistrationKey">
          <key-property name="identifier" column="identifier"/>
          <key-property name="source" column="source"/>
       </composite-id>
       <property name="currentState" column="current_state"/>
      <!--
         Define the "one" end of the one to many, registration->> history, relationship.
         1) The "one" end must be marked as inverse=true.
         2) The cascade=true ensures that the column elements are persisted via reachability
         3) The "order-by" ensures that iteration over the set is done in history order with most
            recent history elements first.
      -->
      <set name="registrationHistory" inverse="true" cascade="all" order-by="history_id asc" table="RegistrationHistory">
            <key>
            <column name="identifier" not-null="true"/>
            <column name="source" not-null="true"/>
         </key>
         <one-to-many class="RegistrationHistoryDTO"/>
        </set>

    </class>
</hibernate-mapping>



RegistrationHistory

Code:
<?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="RegistrationHistoryDTO" table="RegistrationHistory" lazy="true" mutable="false">
         <id name="historyID" column="history_id">
          <generator class="sequence">
                <param name="sequence">seq_hist_id</param>
            </generator>
       </id>
       <property name="whenChanged" column="when_changed" type="timestamp"/>
       <property name="oldState" column="old_state"/>
       <property name="newState" column="new_state"/>

       <!-- The other end of the registration->> history, relationship -->
       <many-to-one name="registration" class="RegistrationDTO"> 
         <column name="identifier" not-null="true"/>
         <column name="source" not-null="true" />      
       </many-to-one>
   </class>
</hibernate-mapping>


RegistrationKey

Code:

import java.io.Serializable;

public class RegistrationKey implements Serializable {

  private Long identifier;
  private String source;


  public RegistrationKey() { }


  public String getSource() {
    return source;
  }


  public void setSource(String source) {
    this.source = source;
  }


  public Long getIdentifier() {
    return identifier;
  }


  public void setIdentifier(Long identifier) {
    this.identifier = identifier;
  }


  public boolean equals(Object o) {
    if (o == null)
      return false;
   
    if (!(o instanceof RegistrationKey))
      return false;

    RegistrationKey key = (RegistrationKey)o;
    if (!this.getIdentifier().equals(key.getIdentifier())
        || !this.getSource().equals(key.getSource()))
      return false;
   
    return true;
  }
 

  public int hashCode() {
    return identifier.intValue() + source.hashCode();
  }
}


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

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.