-->
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: Loading a collection for an entity created from a scalar
PostPosted: Mon May 01, 2006 2:41 am 
Beginner
Beginner

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

Mapping documents:

Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.mig.connectivity.hibernate.Message" table="messages" schema="dbo">
         <meta attribute="implement-equals">true</meta>
      <id name="messageId" type="integer">
         <meta attribute="scope-set">protected</meta>
         <meta attribute="use-in-equals">true</meta>
        <column name="message_id" />
        <generator class="assigned" />
      </id>
      <property name="sourceAddress" type="string">
          <column name="oa" length="30" not-null="true" />
      </property>
      <property name="destinationAddress" type="string">
          <column name="da" length="30" not-null="true" />
      </property>
      <property name="timestamp" type="timestamp">
          <column name="message_timestamp" length="23" not-null="true" />
      </property>
      <property name="outgoingStatus" type="integer">
          <column name="outgoing_status" length="5" not-null="true" />
      </property>
      <property name="sentStatus" type="integer">
          <column name="sent_status" length="5" not-null="true" />
      </property>
      <property name="text" type="string">
          <column name="text" length="2048"/>
      </property>
      <many-to-one name="carrier" lazy="false" class="com.mig.provisioning.db.hibernate.Carrier">
          <column name="service_provider_id" not-null="true" />
      </many-to-one>
      <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>             
    </class>
      <sql-query name="com.mig.connectivity.hibernate.getMessagesForAddressAndProvider">
       <return alias="message" class="com.mig.connectivity.hibernate.Message">
           <return-property name="messageId" column="message_id"/>
           <return-property name="sourceAddress" column="oa"/>
           <return-property name="destinationAddress" column="da"/>
           <return-property name="timestamp" column="message_timestamp"/>
           <return-property name="outgoingStatus" column="outgoing_status"/>
           <return-property name="sentStatus" column="sent_status"/>
           <return-property name="text" column="text"/>
           <return-property name="carrier" column="service_provider_id"/>
       </return>
       <![CDATA[select message_id, oa, da, message_timestamp, outgoing_status, sent_status, text, service_provider_id
       from messages
       where
         message_timestamp >= :startFrom and
         message_timestamp < :endAt and
         ( oa = :number or da = :number ) and
         virtual_provider_id = :providerId and
        service_provider_id <> 48
       order by message_timestamp desc]]>
    </sql-query>
      <sql-query name="com.mig.connectivity.hibernate.getMessagesForAddress" callable="true">
          <!-- Parameters are:
          @start_report_datetime  datetime,
          @end_report_datetime    datetime,
          @address                varchar(30)
          -->
          { call usermessages_resolvedcarrier( ?, ?, ? ) }
    </sql-query>
      <sql-query name="com.mig.connectivity.hibernate.getHistoryStatus">
       <return alias="message" class="com.mig.connectivity.hibernate.MessageNotificationHistory">
           <return-property name="messageNotificationHistoryId" column="message_notification_historyid"/>
           <return-property name="protocolMessageId" column="protocol_message_id"/>
           <return-property name="notification" column="notification"/>
           <return-property name="notifiedOn" column="notified_on"/>
           <return-property name="additionalInfo" column="additional_info"/>
           <return-property name="doneDate" column="done_date"/>
           <return-property name="messageId" column="message_id"/>
       </return>
       <![CDATA[select message_notification_historyid, protocol_message_id, notification, notified_on, additional_info, done_date, message_id
       from message_notification_history
       where message_id = :messageId
       order by notified_on desc]]>
    </sql-query>
</hibernate-mapping>



I call a stored procedure which returns a scalar, from which I manually created a transient entity, like so:

Code:
  public static List<Message> getMessagesForAddress( Session session,
      Timestamp fromDate, Timestamp toDate, String address )
    throws Exception
  {
    Query q = session.getNamedQuery( "com.mig.connectivity.hibernate.getMessagesForAddress" );
   
    int p = 0;
    q.setTimestamp( p++, fromDate );
    q.setTimestamp( p++, toDate );
    q.setString( p++, address );
   
    List<Object[]> l = q.list();
    ArrayList<Message> _messageList = new ArrayList<Message>( );
   
    for( Object[] _o: l ) {
      Message _newMessage = new Message();
      _newMessage.setMessageId( (( BigDecimal) _o[0]).intValue() );
      _newMessage.setSourceAddress( (String) _o[1] );
      _newMessage.setDestinationAddress( (String) _o[2] );
      _newMessage.setTimestamp( (Timestamp) _o[3] );
      _newMessage.setOutgoingStatus( (( BigDecimal) _o[4]).intValue() );
      _newMessage.setSentStatus( (( BigDecimal) _o[5]).intValue() );
      _newMessage.setText( (String) _o[6] );
      Carrier carrier = CarrierDAO.getCarrier( session, (Integer) _o[7] );
      carrier.getName(); // force loading of properties
      _newMessage.setCarrier( carrier );
      _newMessage.setNotificationHistories(
          new HashSet( MessageDAO.getStatusHistory( session, _newMessage )));
     
      _messageList.add( _newMessage );
    }
   
    return _messageList;   
  }

  private static List<MessageNotificationHistory> getStatusHistory( Session session, Message message ) {
    Query q = session.getNamedQuery( "com.mig.connectivity.hibernate.getHistoryStatus" );
   
    q.setInteger( "messageId", message.getMessageId() );
    return q.list();
  }


Because the return value was scalar, and I was creating the entity from the scalar returned from the stored proc, the collection for the set named notificationHistories is never populated. Thus, I have to manually populate the set using the method getStatusHistory() above. However, because of this, even if the SQL has an "order by" clause, because it was copied to a HashSet, the ordering is sometimes lost.

Is there a better way so that Hibernate will load the set for an entity that was created from a scalar ? I know I could have done a:

Code:
session.load( Message, (( BigDecimal) _o[0]).intValue() )


.. in the getMessagesForAddress() method, but that would load each row twice! Once by the stored proc as a scalar, and twice by Hibernate as an entity. I also want the set to be "lazy=true", which is what is specified in the mapping document ,as I dont want the set to be always loaded for a specific Message.


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.