-->
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: Mapping a column more than once
PostPosted: Thu Aug 03, 2006 9:40 pm 
Beginner
Beginner

Joined: Mon Nov 07, 2005 11:10 pm
Posts: 30
Hibernate version: 3.1.2

The Hibernate on-line reference says:

Quote:
update, insert (optional - defaults to true) : specifies that the mapped columns should be included in SQL UPDATE and/or INSERT statements. Setting both to false allows a pure "derived" property whose value is initialized from some other property that maps to the same colum(s) or by a trigger or other application.


Mapping documents:


Snippet from the Message ( parent ) mapping file:
Code:
      <id name="messageId" type="integer">
         <meta attribute="scope-set">protected</meta>
         <meta attribute="use-in-equals">true</meta>
        <column name="message_id" />
        <generator class="native" />
      </id>
      <set name="notificationHistories" lazy="true" inverse="true" order-by="notified_on desc">
          <key>
              <column name="message_id" not-null="true" />
          </key>
          <one-to-many class="com.mig.connectivity.hibernate.MessageNotificationHistory" />
      </set>


Snippet from the MessageNotificationHistory ( child ) mapping file:
Code:
      <property name="messageId" type="integer">
          <column name="message_id" not-null="true" />
      </property>
      <many-to-one name="message" lazy="no-proxy" class="com.mig.connectivity.hibernate.Message" insert="false" update="false">
          <column name="message_id" not-null="true" />
      </many-to-one>


The reason that I want to do this is that ... there are several cases where I already have the id for the foreign key ( obtained elsewhere ... from a legacy system, properties file, or other non-Hibernate means ).

Thus, I don't want to have Hibernate load the parent entity Message every time a new child entity MessageNotificationHistory is being persisted to the database. This means that I don't want Hibernate to do a SELECT on the parent table every time I do an INSERT into the child table. However, that is what Hibernate currently does. There will be times that after loading the child entity, I then want to tell Hibernate to load the parent entity lazily.

So, I tried to map the column twice ... once using a many-to-one to the parent entity, and the second as a normal property as an integer. The on-line reference says this is possible:

Quote:
Setting both to false allows a pure "derived" property whose value is initialized from some other property that maps to the same colum(s)


However, what I get is the stack trace below:

Full stack trace of any exception that occurs:

Code:
org.hibernate.MappingException: Repeated column in mapping for entity: com.mig.connectivity.hibernate.MessageNotificationHistory column: message_id (should be mapped with insert="false" update="false")
        at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:575)
        at org.hibernate.mapping.PersistentClass.checkPropertyColumnDuplication(PersistentClass.java:597)
        at org.hibernate.mapping.PersistentClass.checkColumnDuplication(PersistentClass.java:615)
        at org.hibernate.mapping.PersistentClass.validate(PersistentClass.java:405)
        at org.hibernate.mapping.RootClass.validate(RootClass.java:192)
        at org.hibernate.cfg.Configuration.validate(Configuration.java:984)
        at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1169)
        at com.mig.hibernate.HibernateUtil.<clinit>(HibernateUtil.java:32)
        at softgame.gateway.connectors.smpp.AbstractDeliveryReceiptConsumer.saveSubmitResp(AbstractDeliveryReceiptConsumer.java:408)
        at softgame.gateway.connectors.smpp.DeliveryReceiptJMSConsumerImpl.run(DeliveryReceiptJMSConsumerImpl.java:266)
        at java.lang.Thread.run(Thread.java:595)


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 04, 2006 12:22 am 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Move the insert/update="false" to the proerty, not the many-to-one.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 04, 2006 1:00 am 
Beginner
Beginner

Joined: Mon Nov 07, 2005 11:10 pm
Posts: 30
But I do want to include that integer property in the insert, such that I only specify:

Code:
Integer id = 1234;
MessageNotificationHistory.setMessageId( id ) ;


instead of

Code:
Message msg = session.load( Message.class, someOtherId );
MessageNotificationHistory.setMessage( msg ) ;


I don't want to load the Message entity ( either programatically as above ... or by Hibernate behind the scense ) just to persist a new MessageNotificationHistory entity.

[/code]


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 04, 2006 1:26 am 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Ah. That will create lots of headaches for you later, seeing a Message will look different after you load it. You should consider changing your mind about this.

Nonetheless it can be done. Your options are:
  1. Change the set to be the "dominant" side of the relationship: remove the inverse="true". Don't both putting the Message into the MessageNotificationHisory, that'll happen automatically when you refresh your Message entity.
  2. Change your many-to-one to not use insert/update=false, but to use <formula> instead of <column>. This tells hibernate that it's a derived property (or relation, in this case), and derived properties are never saved.

_________________
Code tags are your friend. Know them and use them.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Aug 04, 2006 4:39 am 
Beginner
Beginner

Joined: Mon Nov 07, 2005 11:10 pm
Posts: 30
I upgraded to Hibernate 3.1.3. That seems to have fixed the problem without changing the mapping file. Found this in the release notes ( note the bold line that I highlighted ):

Quote:
Changes in version 3.1.3 (2006.03.20)
-------------------------------------------

** Bug
* [HHH-535] - properties element causes exception in interface/abstract class
* [HHH-1236] - Remove static reference to classloader, to avoid memory leak at webapp reload
* [HHH-1248] - explicit joins to collections in subquery result in join conditions being dropped from sql
* [HHH-1287] - Problem with WAS ExtendedJTATransaction not available when using MDB
* [HHH-1325] - ArrayOutOfBounds expected in DatabaseMetadata.isTable when specifing schema
* [HHH-1419] - Update + Exists doesn't seem to work
* [HHH-1433] - many-to-many with additional 'with' join clause generates bad sql
* [HHH-1435] - many-to-one lazy seems to be broken in 3.1.x
* [HHH-1445] - SchemaUpdate closes shared ConnectionProvider
* [HHH-1453] - Broken exception handling in NullableType
* [HHH-1464] - QueryException from Query.getReturnAliases when query uses "fetch"
* [HHH-1486] - Concurrent access issues with both SoftLimitMRUCache and SimpleMRUCache
* [HHH-1489] - mapped composite is is always assumed as transient
* [HHH-1508] - Session.createQuery() should not flush the session
* [HHH-1531] - NPE with many-to-many and property-ref
* [HHH-1546] - generated version properties fail with multiple actions per flush
[/b][/quote]


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.