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.