-->
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.  [ 7 posts ] 
Author Message
 Post subject: load-collection with many-to-many no longer works in 3.2CR3
PostPosted: Wed Jul 12, 2006 5:45 pm 
Newbie

Joined: Tue Sep 13, 2005 6:23 pm
Posts: 9
We have the following mapping, which works fine with Hibernate 3.0.5:

Code:
<bag name="lineCodes">
  <key>
    <column name="GCM_ID"/>
    <column name="MANF_UPC_C"/>
  </key>
  <many-to-many class="LineCode">
    <column name="LC_MANF_UPC_C" />
    <column name="LINE_CODE" />
  </many-to-many>
  <loader query-ref="pack_line_codes" />
</bag>

 
<sql-query name="pack_line_codes">
  <load-collection alias="a" role="CampaignFinishedProduct.lineCodes" />
  with rawData as (
    select gcm_id, manf_upc_c, manf_upc_c as lc_manf_upc_c, line_code
    from gpmq.pack_line_codes )
  select {a.*}
    from rawData a
    where a.gcm_id = ?
    and a.manf_upc_c = ?
</sql-query>


However, it no longer works in 3.2CR3. I get a NullPointerException from within Hibernate. I have jack'd with the Hibernate Code, and modified the SQLQueryReturnProcessor::addCollection(String, String, Map ) method to add the following conditional: || collectionPersister.isManyToMany(), as below to fix the Exception:

Code:
   private void addCollection(String role, String alias, Map propertyResults) {
      SQLLoadableCollection collectionPersister = ( SQLLoadableCollection ) factory.getCollectionPersister( role );
      alias2CollectionPersister.put( alias, collectionPersister );
      String suffix = generateCollectionSuffix();
      log.trace( "mapping alias [" + alias + "] to collection-suffix [" + suffix + "]" );
      alias2CollectionSuffix.put( alias, suffix );
      collectionPropertyResultMaps.put( alias, propertyResults );

      if ( collectionPersister.isOneToMany() || collectionPersister.isManyToMany() ) {
         SQLLoadable persister = ( SQLLoadable ) collectionPersister.getElementPersister();
         addPersister( alias, filter( propertyResults ), persister );
      }
   }


This results in an SQL Statement that has all the columns from the look-up table, as well as the table containing the related entity. My custom SQL is only returning the columns from the lookup-table.

It seems that the following block of code in the SQLQueryParser::resolveCollectionProperties(String, String) method is not correct:

Code:
      if ( "*".equals( propertyName ) ) {
         if( !fieldResults.isEmpty() ) {
            throw new QueryException("Using return-propertys together with * syntax is not supported.");
         }
         
         String selectFragment = collectionPersister.selectFragment( aliasName, collectionSuffix );
         aliasesFound++;
         return selectFragment
                  + ", "
                  + resolveProperties( aliasName, propertyName );
      }


In my case, I would be happy if it just returned selectFragment.

I have also tried jackin' with the code to just return selectFragment for the many-to-many case, but then Hibernate is not able to parse the results, as it is trying to find columns in the result set that are part of the related entity, not the lookup-table which is what is being queried.

Why is 3.2CR3 acting differently than 3.0.5? It really seems like many-to-many relationships and sql-query/load-collection are not supported anymore.

I would really like to use 3.2CR3, because of the advertized fix: HHH-1792 which I need to have as I am using IBM UDB 7.2 as my database; and trying to use stored procedures to implement the INSERT/DELETE functionality on the lookup table in the above mapping.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jul 12, 2006 6:15 pm 
Hibernate Team
Hibernate Team

Joined: Tue Aug 26, 2003 3:00 pm
Posts: 1816
Location: Austin, TX
There were significant changes to how native sql queries are handled in 3.2.0.cr3: http://opensource.atlassian.com/project ... elog-panel


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 13, 2006 10:54 am 
Newbie

Joined: Tue Sep 13, 2005 6:23 pm
Posts: 9
I have changed my test environment to change the lookup table for the many-to-many join to work with normal Hibernate schematics; added extra key column, LC_MANF_UPC_C to the PACK_LINE_CODES table. ( In production environment this column is not present, and the MANF_UPC_C column is used in both foreign keys of the many-to-many relationship. )

When I run my app, the following SQL is generated:

Code:
select
   linecodes0_.GCM_ID as GCM1_1_,
   linecodes0_.MANF_UPC_C as MANF2_1_,
   linecodes0_.LC_MANF_UPC_C as LC3_1_,
   linecodes0_.LINE_CODE as LINE4_1_,

   linecode1_.UPC as UPC0_,
   linecode1_.LINE_CODE as LINE2_0_,
   linecode1_.DESCRIPTION as DESCRIPT3_43_0_,
   linecode1_.UOM as UOM43_0_,
   linecode1_.UNITS_PER_SKU as UNITS5_43_0_,
   linecode1_.INVENTORY_ON_HAND as INVENTORY6_43_0_,
   linecode1_.LAST_INVENTORY_UPDATE as LAST7_43_0_
from GPMQ.PACK_LINE_CODES linecodes0_
   inner join GPMQ.CARMA_LINE_CODES_V linecode1_
      on linecodes0_.LC_MANF_UPC_C=linecode1_.UPC
      and linecodes0_.LINE_CODE=linecode1_.LINE_CODE
where linecodes0_.GCM_ID=? and linecodes0_.MANF_UPC_C=?


So, I can see that my custom SQL is not correct as shown in the previous post.

However, even if I change the query to look like this, I still think I will get the NullPointerException from Hibernate because of the missing conditional in the SQLQueryReturnProcessor::addCollection(String, String, Map ) method as noted in the previous posting.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jul 13, 2006 6:13 pm 
Newbie

Joined: Tue Sep 13, 2005 6:23 pm
Posts: 9
I have gotten Hibernate 3.2CR3 to work with my modified sql-query mapping; but only after making the following change to SQLQueryReturnProcessor::addCollection(String, String, Map ).

The conditional, needs to also check for many-to-many in order to get the columns for the fetch join to work correctly:

Added code: || collectionPersister.isManyToMany()

Code:
   private void addCollection(String role, String alias, Map propertyResults) {
      SQLLoadableCollection collectionPersister = ( SQLLoadableCollection ) factory.getCollectionPersister( role );
      alias2CollectionPersister.put( alias, collectionPersister );
      String suffix = generateCollectionSuffix();
      log.trace( "mapping alias [" + alias + "] to collection-suffix [" + suffix + "]" );
      alias2CollectionSuffix.put( alias, suffix );
      collectionPropertyResultMaps.put( alias, propertyResults );

      if ( collectionPersister.isOneToMany() || collectionPersister.isManyToMany() ) {
         SQLLoadable persister = ( SQLLoadable ) collectionPersister.getElementPersister();
         addPersister( alias, filter( propertyResults ), persister );
      }
   }


Without the code change, Hibernate will throw a NullPointerException in SQlQueryParser::resolveProperties(String, String ) since it can't find an entity persister.

Should this be reported as a bug?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 19, 2006 1:35 pm 
Newbie

Joined: Wed Dec 13, 2006 3:34 pm
Posts: 4
I see this question is dated almost a year back ago. I am currently using the lastest release and facing the same NullPointerException. Were you able to figure out an alternative solution other than modifying the under lying code?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 19, 2006 2:05 pm 
Newbie

Joined: Tue Sep 13, 2005 6:23 pm
Posts: 9
In the end we convinced our DBA's that the way the data relationship was modeled in the DB was wrong, and we could use more standard mapping with the version of Hibernate we were currently using ( 3.0 ).

If you are getting the same issue, I would press to see if this needs to be reported as a Hibernate bug.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Dec 19, 2006 7:15 pm 
Newbie

Joined: Wed Dec 13, 2006 3:34 pm
Posts: 4
I was getting that error because of the alias name. Once I added a return alias name it ran fine but with wrong data.

I tried to use loader query to load my mapping for many-to-many relationship as i wanted only a few columns from the final associated class and not the huge pile of data. I must have surely mapped it wrong as during loading it completely missed the mapping and passed the initial value as the input parameter.

Following is the mapping for your reference.

[b] Employee
<class name="Employee">
.....
.....
<bag name="messages" table="MSG_DETAIL" inverse="true">
<key column="EMP_ID"/>
<many-to-many class="Message" column="MSG_ID" />
</class>


Message
<class name="Message">
.....
.....
<bag name="employees" table="MSG_DETAIL">
<key column="MSG_ID"/>
<many-to-many class="Employee"column="EMP_ID"/>
<loader query-ref="loadEmployees" />
</bag>
</class>


<sql-query name="loadEmployees">
<return alias="EMP" class="Employee"/>
<load-collection alias="EMP"
role="Message.employees" />
SELECT
EMP.EMP_ID AS {emp.emplId},
EMP.ACTIVE_IND AS {emp.activeIndicator},
EMP.FIRST_NAME AS {emp.firstName},
EMP.JOB_TITLE AS {emp.jobTitle},
EMP.LAST_NAME AS {emp.lastName},
EMP.MIDDLE_INITIAL AS {emp.middleInitial}
FROM
Employee EMP
WHERE EMP_ID = :EMP_ID
</sql-query>

[/b]

I wasnt sure how to load the collection with a join query to msg_detail table as there is no mapping for the table for hibernate to understand.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 7 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.