I am a little confused because 1) I thought this *was* working, now it's stopped and I'm not sure what I did, and 2) I thought this was THE solution to my problem:
Objects (and their children) can be exported out to XML. The XML can be modified, and then reimported, and I need to save any changes to the db. Additionally, objects may be created externally (by another instance of the application, and therefore given an appropriate ID value (uuid.hex)), which need to be imported and inserted into the DB.
After much futzing about, I discovered saveOrUpdateCopy( obj ), which looked like THR answer. And it worked!
But now I am getting a NonUniqueObjectException when I reimport the object.
(Simplified) mapping looks like:
<class name="&isis_pkg;.Station" >
<id name="uid" type="string" unsaved-value="any" >
<meta attribute="scope-field">private</meta>
<column name="uid" length="32" />
<generator class="assigned"/>
</id>'
<version name="modTime" type="timestamp"
unsaved-value="undefined" />
<property name="siteName"
type="string"
not-null="&FLEX_NULL;" />
<property name="code"
type="string" >
<column name="code"
sql-type="char(5)"
not-null="&FLEX_NULL;" />
</property>
<set name="telemetry"
lazy="false" inverse="true"
cascade="all" >
<key column="stationId" />
<one-to-many class="&isis_pkg;.StationTelemetry" />
</set>
[more properties and collections ommitted]
</class>
I had to go with assigned ids because otherwise hibernate would change them when the externally-created objects were inserted. (Or so I believe.)
The DbMgr code is:
public boolean synch( DbObject externalObject )
{
Transaction tx = null;
try {
Session sess = getCurrentSession();
tx = sess.beginTransaction();
sess.saveOrUpdateCopy(externalObject);
tx.commit();
return true;
}
catch (HibernateException he) {
he.printStackTrace(); // debugging
if (tx!=null)
try{ tx.rollback(); }
catch ( HibernateException hex )
{ hex.printStackTrace(); }
he.printStackTrace();
return false;
}
}
op of thel stack trace is:
[java] net.sf.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: 402826ccfc5709ca00fc570a1af30002, of class: edu.iris.dmc.isis.Station
[java] at net.sf.hibernate.impl.SessionImpl.doSave(SessionImpl.java:834)
[java] at net.sf.hibernate.impl.SessionImpl.saveWithGeneratedIdentifier(SessionImpl.java:772)
[java] at net.sf.hibernate.impl.SessionImpl.doCopy(SessionImpl.java:4004)
[java] at net.sf.hibernate.impl.SessionImpl.saveOrUpdateCopy(SessionImpl.java:3971)
[java] at edu.iris.dmc.db.DbMgr.synch(DbMgr.java:234)
[java] at edu.iris.dmc.isis.Isis.aoSync(Isis.java:211)
[java] at edu.iris.dmc.ui.AppFrame.importFile(AppFrame.java:137)
The javadocs say
Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved or does not exist in the database, save it and return it as a newly persistent instance. Otherwise, the given instance does not become associated with the session.
Which is exactly the behaviour I want. Yet, something is unhappy.
What is really confusing me is that I *swear* this worked, at least for the simple case of empty collections...
Since this is a stand-alone, single-user sort of application with lazy loads on several large collections, I'm using the "anti-pattern" of a single long-running session for the application. (I'm sure that is frowned upon.)
Using Hibernate 2.1.3, MySQL db, Java 1.4.2, Swing UI
Any insight would be much appreciated!
Thanks,
Linus
|