Hi all,
I seem to have come across a point where what I see in the
hibernate source code and what I understand from Chapter 6
of the Hibernate Reference doc disagree -- so I figure that it is
my understanding that is flawed. I need some guidance telling
me what it is I am doing wrong with my mapping.
I have a set that contains strings, as shown below. This forum
is rich with examples of entity relation mappings in sets, but
I haven't found any with simple strings. My problem is that the
owning class (AttributeSet) is persisted to the database properly,
but the contained set is not persisted. Only the single SQL
statement to insert the comparatorClassNamve value is issued.
I used the eclipse debug mode to follow the execution path and
discovered that this set is expected to be cascaded after the
parent class is persisted. I then get to the following code from
net.sf.hibernate.engine.Cascades:
Code:
/**
* Cascade an action to the child or children
*/
private static void cascade(
SessionImplementor session,
Object child,
Type type,
CascadingAction action,
CascadeStyle style,
int cascadeTo,
Object anything
) throws HibernateException {
if (child!=null) {
if ( type.isAssociationType() ) {
if ( ( (AssociationType) type ).getForeignKeyDirection().cascadeNow(cascadeTo) ) {
if ( type.isEntityType() || type.isObjectType() ) {
/*if ( style.doCascade(session, child) )*/ action.cascade(session, child, anything);
}
else if ( type.isPersistentCollectionType() ) {
final int cascadeVia;
if ( cascadeTo==CASCADE_AFTER_INSERT_BEFORE_DELETE) {
cascadeVia = CASCADE_AFTER_INSERT_BEFORE_DELETE_VIA_COLLECTION;
}
else {
cascadeVia = cascadeTo;
}
PersistentCollectionType pctype = (PersistentCollectionType) type;
CollectionPersister persister = session.getFactory().getCollectionPersister( pctype.getRole() );
Type elemType = persister.getElementType();
//cascade to current collection elements
if ( elemType.isEntityType() || elemType.isObjectType() || elemType.isComponentType() ) {
cascadeCollection(action, style, pctype, elemType, child, cascadeVia, session, anything);
}
}
}
}
else if ( type.isComponentType() ) {
AbstractComponentType componentType = (AbstractComponentType) type;
Object[] children = componentType.getPropertyValues(child, session);
Type[] types = componentType.getSubtypes();
for ( int i=0; i<types.length; i++ ) {
CascadeStyle componentPropertyStyle = componentType.cascade(i);
if ( componentPropertyStyle.doCascade(action) ) cascade(
session, children[i], types[i], action, componentPropertyStyle, cascadeTo, anything
);
}
}
}
}
The statement of interest is:
Code:
//cascade to current collection elements
if ( elemType.isEntityType() || elemType.isObjectType() || elemType.isComponentType() ) {
cascadeCollection(action, style, pctype, elemType, child, cascadeVia, session, anything);
}
as should probably be expected when elemType == stringType, which
eclipse assured me it was. Because the if() evaluates to false, the cascade()
call returns, and no set contents are persisted.
So -- what am I doing wrong? There is an example in section 6.3 of
a set containing strings:
Quote:
Some examples, first, a set of strings:
<set name="names" table="NAMES">
<key column="GROUPID"/>
<element column="NAME" type="string"/>
</set>
and while my Xdoclet-generated mapping file has a few more
attributes defined, it certainly seems like this should work.
As you may notice, in this mapping file one thing that differs
from the example is that I had set cascade=all. I also tried
this example with the default value (none). In that case, no
cascade was attempted (as expected) but the persister.hasCollections()
was "true" -- and still the set of strings did not get persisted
(no insert statement was ever generated either).
So...help? I really did read chapter 6. And all the other
chapters. Several times. So it must just be my ability to
understand what those of you who got this sort of thing
working with no problems already do understand....
Thanks so much,
-Jen
Hibernate version: 2.1.6
Mapping documents:Code:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class
name="edu.se.evolution.kenyon.util.AttributeSet"
dynamic-update="false"
dynamic-insert="false"
>
<id
name="id"
column="id"
type="java.lang.Long"
>
<generator class="native">
</generator>
</id>
<set
name="me"
lazy="false"
inverse="false"
cascade="all"
sort="unsorted"
>
<key
column="attribute_set_id"
>
</key>
<element
column="value"
type="string"
not-null="false"
unique="false"
/>
</set>
<property
name="comparatorClassName"
type="java.lang.String"
update="true"
insert="true"
access="property"
column="comparatorClassName"
/>
<!--
To add non XDoclet property mappings, create a file named
hibernate-properties-AttributeSet.xml
containing the additional properties and place it in your merge dir. -->
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():(Junit test. I used the documentation's suggested HibernateUtil
with a modified Configuration constructor using .addClass()).
Code:
public void testPersisting() throws HibernateException
{
mySet = new AttributeSet();
mySet.add("ro");
mySet.add("jen");
mySet.add("areya");
printContents();
mySet.sortWith(new lenComparator());
printContents();
Session session = HibernateUtil.currentSession();
Transaction tx= session.beginTransaction();
session.save(mySet);
tx.commit();
HibernateUtil.closeSession();
}
Full stack trace of any exception that occurs:
No execptions occur.
Name and version of the database you are using:
MySQL 3.23.56
Debug level Hibernate log excerpt:
Nothing wrong happens, but not everything I expected to happen
did happen.