Hibernate version: 2.1.6, running against MySQL 4.1.x inside jboss 3.2
I have a problem converting a relationship from being coded to being
specified in hibernate. Here's the simplified test case.
We're representing categorised FAQs.
A FAQ category has the following properties
id - java.lang.Long
title - java.lang.Long
faqs - java.util.List
A FAQ has the following properties:
id - java.lang.Long
catId - java.lang.Long
position - java.lang.Long
title - java.lang.Long
All properties have simple setter/getter methods:
Code:
public void setProp(Type propval) {
this.prop = propval;
}
public Type getProp() {
return this.prop;
}
ALL types are class types - no primitives.
And here's the mapping doc:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="FAQCategory"
table="faq_category"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
>
<id name="id"
column="id"
type="long">
<generator class="native"/>
</id>
<property
name="title"
type="string"
update="true"
insert="true"
access="property"
column="title"
/>
</class>
<class name="FAQ"
table="faq"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
>
<id name="id"
column="id"
type="long">
<generator class="native"/>
</id>
<property
name="catId"
type="long"
update="true"
insert="true"
access="property"
column="category_id"
/>
<property
name="position"
type="long"
update="true"
insert="true"
access="property"
column="position"
/>
<property
name="title"
type="string"
update="true"
insert="true"
access="property"
column="title"
/>
</class>
</hibernate-mapping>
Now - I want to avoid having the following logic:
1) Get all categories
2) For each category get all faqs - collect into a list and call the
setFaqs method
Note - a faq has to be in a category but in the web tier can be
handled as an object by itself. Lazy fetch is set to false - I want
the fully populated object in the web-tier where the objects are
detached from the session (we're not talking a large number of objects
nor will it grow so large either)
It seems from the docs that a bi-directional parent/child relationship
would be good here.
So - a modified mapping doc:
Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="FAQCategory"
table="faq_category"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
>
<id name="id"
column="id"
type="long">
<generator class="native"/>
</id>
<property
name="title"
type="string"
update="true"
insert="true"
access="property"
column="title"
/>
<!-- New section -->
<list name="faqs"
lazy="false"
inverse="false"
cascade="save-update"
>
<key column="category_id"/>
<index column="position"/>
<one-to-many class="FAQ"/>
</list>
<!-- End new section -->
</class>
<class name="FAQ"
table="faq"
dynamic-update="false"
dynamic-insert="false"
select-before-update="false"
>
<id name="id"
column="id"
type="long">
<generator class="native"/>
</id>
<!-- Changed section -->
<many-to-one
name="catId"
class="FAQCategory"
cascade="none"
outer-join="auto"
update="false"
insert="true"
access="property"
column="category_id"
not-null="true"
/>
<!-- End changed section -->
<property
name="position"
type="long"
update="true"
insert="true"
access="property"
column="position"
/>
<property
name="title"
type="string"
update="true"
insert="true"
access="property"
column="title"
/>
</class>
</hibernate-mapping>
This gives the error
Code:
2005-01-20 15:26:33,954 ERROR [net.sf.hibernate.impl.IteratorImpl] could not get next result net.sf.hibernate.PropertyAccessException: exception setting property value with CGLIB (set hibernate.cglib.use_reflection_optimizer=false for more info) setter of setCategoryId
This is:
Code:
Caused by: net.sf.cglib.beans.BulkBeanException
at FAQ$$BulkBeanByCGLIB$$b575d9a5.setPropertyValues(<generated>)
at net.sf.hibernate.persister.AbstractEntityPersister.setPropertyValues(AbstractEntityPersister.java:208)
Caused by: java.lang.ClassCastException
Now - this is running under jboss 3.2 using a .sar archive
(jboss-service.xml) - I'm not sure how to set the reflection property
in this file. I have set the property to false in the jmx-console and
restarted the hibernate service from there - but I still get the exact
same message.
Now - PropertyAccessExceptions are queried and answered many times in
the forum - and each time it's something to do with calling a setter
method with the wrong type parameter - often where the parameter is a
primitive and the column has a NULL value.
However - this setter is setting an ID which is specified in the
mapping as "long" and ALL the hibernate "long" types in the system are
java.lang.Long - we don't use primitives at this level in the code.
In all likelihood this is a simple config mistake in the mapping doc
but I've been staring at this all day - so I was hoping a fresh pair
of eyes would see what I've misunderstood :-)