Hibernate version: 2.1
Name and version of the database you are using: Firebird 1.5
I've tried to map a Device object that has a set of Feature objects (see below).
After that, I wrote code to create a Device and a Feature, add the Feature
to the Device's set and save the Device. The intent was to save the Feature
as well via transitive persistence.
My initial problem was that when I called device.getFeatures().add(feature), I
got a NullPointerException in device.getFeatures() because there was no set.
I added a line in the Device constructor to create a new HashSet() - should I
have had to?
Now my problem is with the transitive persistence part. With or without
the cascade="all" in the mapping for Device, if I try to only save the
Device, the SQL I get seems to show an attempt to INSERT the Device and
UPDATE the Feature. The UPDATE fails because the Feature is not yet in
the table. The UPDATE appears to correspond to the feature.setFeatureName() call.
WITHOUT the cascade="all", if I save both the Device and the Feature, the
SQL shows an INSERT for each object, plus an UPDATE of the Feature to set
its foreign key to the DEVICE table.
WITH the cascade="all", if I save both the Device and the Feature, I get
the INSERT for the Device and the update for the Feature as before.
I'm sure I'm doing something dumb - can anyone see what? Most of the
examples that I've seen with cascade="all" have been for bi-di
associations - that's not a requirement, is it?
Thanks,
-Jeff
-------------------------------------------------------------------------------
Mapping documents:
<hibernate-mapping>
<class name="domain.Device" table="DEVICE">
<id name="id" column="device_id">
<generator class="hilo"/>
</id>
<property name="model"/>
<property name="ipAddress"/>
<set name="features" lazy="true" cascade="all">
<key column="device_id"/>
<one-to-many class="domain.Feature"/>
</set>
</class>
</hibernate-mapping>
<hibernate-mapping >
<class name="domain.Feature" table="FEATURE">
<id name="id" column="feature_id">
<generator class="hilo"/>
</id>
<property name="featureName"/>
</class>
</hibernate-mapping>
-------------------------------------------------------------------------------
Code between sessionFactory.openSession() and session.close():
(I am using the Spring framework to wrap things in transactions, but I've
done this same thing directly through Hibernate with the same results as above.)
Device device = new Device();
device.setIpAddress("157.184.70.140");
device.setModel("Optra");
Feature feature = new Feature();
feature.setFeatureName("Color");
device.getFeatures().add(feature);
session.save(device);
//session.save(feature);
-------------------------------------------------------------------------------
The generated SQL (show_sql=true):
Hibernate: insert into DEVICE (model, ipAddress, device_id) values (?, ?, ?)
Hibernate: update FEATURE set featureName=? where feature_id=?
[/code]
|