Why is ColdFusion/Hibernate adding the entity name as a prefix to column names in generated SQL?
I am running ColdFusion 9.01 with all the latest hotfixes applied as of this writing. I've been using ColdFusion 9's Hibernate integration on a production site for well over a year and now need to relate two existing entities; however, Hibernate is generating incorrect column names for a many-开发者_高级运维to-many relationship.
My two existing entities are Presenter and Product. I have dbcreate set to "none" and am using the default values for autogenmap on a Oracle 11g database. So, Hibernate is not responsible for schema changes to my database.
Here is the new property I added to my Presenter entity.
/** Relation to any episodes associated to this presenter. **/
property name='Products' fieldtype='many-to-many' lazy='extra'
singularName="Product" cfc='platform.shared.models.entities.Product' fkcolumn='PRESENTER_ID'
linktable='PRESENTERS_TO_PRODUCTS' cacheuse = 'read-only' cachename = 'EntityCache' inversejoincolumn='PRODUCT_ID';
Here is the invalid SQL generated by Hibernate.
select count(Product_product_id) from PRESENTERS_TO_PRODUCTS where Presenter_presenter_id =?
I am unsure why Hibernate is prefixing the columns with the name of the entity. The SQL should look like this:
select count(product_id) from PRESENTERS_TO_PRODUCTS where presenter_id =?
As I diagnose this, I saved the HBXML files generated by Hibernate. I've included the full file for my Presenter entity below.
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class entity-name="Presenter" lazy="true"
name="cfc:platform.shared.models.entities.Presenter" table="PRESENTERS">
<id name="presenter_id" type="integer">
<column name="presenter_id"/>
<generator class="increment"/>
</id>
<property name="presenter_bio" type="text">
<column name="presenter_bio"/>
</property>
<property name="presenter_name" type="text">
<column name="presenter_name"/>
</property>
<property name="presenter_website" type="text">
<column name="presenter_website"/>
</property>
<property name="presenter_company" type="text">
<column name="presenter_company"/>
</property>
<property name="presenter_internalname" type="text">
<column name="presenter_internalname"/>
</property>
<property name="presenter_logo" type="integer">
<column name="presenter_logo"/>
</property>
<property name="presenter_description" type="text">
<column name="presenter_description"/>
</property>
<property name="deleted" type="integer">
<column name="deleted"/>
</property>
<property name="presenter_is_evangelist" type="integer">
<column name="presenter_is_evangelist"/>
</property>
<property name="presenter_is_expert" type="integer">
<column name="presenter_is_expert"/>
</property>
<property name="presenter_about" type="text">
<column name="presenter_about"/>
</property>
<bag lazy="extra" name="Episodes" table="ASSET_TO_PRESENTERS">
<cache region="EntityCache" usage="read-only"/>
<key column="PRESENTER_ID"/>
<many-to-many
class="cfc:platform.shared.models.entities.Episode" column="ASSET_ID"/>
</bag>
<!-- This is the new relationship causing trouble -->
<bag lazy="extra" name="Products" table="PRESENTERS_TO_PRODUCTS">
<cache region="ATVEntityCache" usage="read-only"/>
<key column="PRESENTER_ID"/>
<many-to-many
class="cfc:platform.shared.models.entities.Product"
column="PRODUCT_ID" not-found="ignore"/>
</bag>
<!-- End new relationship -->
<many-to-one
class="cfc:platform.shared.models.entities.AttachmentImage"
column="presenter_photo" lazy="proxy" name="Photo"/>
</class>
</hibernate-mapping>
Much appreciated.
**** UPDATE 1 **** I've added the inversejoincolumn column. I am able to access the products in my unit test with the following assertions, however, when I dump the entity, the error shows itself.
var p = entityLoadByPK('Presenter',276);
var pr = p.getProducts();
// Works
assertEquals(2,arrayLen(pr),'Expected 2 products');
// Also works
assertEquals('ProductA',pr[1].getproduct_name(),'Incorrect product name.');
// Also works
assertEquals('ProductB',pr[2].getproduct_name(),'Incorrect product name.');
// Fails
writeDump(var=p,top=2,abort=true);
**** UPDATE 2 **** I've awarded the solution; however, something is still off. I've attached a screenshot of the DUMP showing the remaining issue. ColdFusion says "[undefined array element] could not retrieve collection size: [Product.Presenters#0]".
Whenever I use a many to many relationship, i always have a inversejoincolumn attribute. I think it is just guessing it because it is not defined explicitly. Here are what my relationships always look like:
property name="names" singularname="name" fieldtype="many-to-many"
cfc="cfc" linktable="linktable" fkcolumn="ThisId"
inversejoincolumn="otherId";
精彩评论