cirrus.hibernate.impl.RelationalDatabaseSession.find() recurse
indefinitely, if the id of the object can't be found (resulting in a
StackOverflowException). The check, if the object is succesfully
retrieved, is performed _after_ the recursion and so is never executed.
To fix this, line 559 ("if (!success) throw new...") has to be moved to
553 (after "deferLoads--;" and _before_ "if (deferLoads==0 ..."),
resulting in the folowing:
551 deferLoads--;
552
553 if (!success) throw new HibernateException("id
not found or provided object was wrong class");
554
555 // now actually load the state into all the
waiting objects...
556 // this code is _not_ executed recursively
557 if (deferLoads==0) doDeferredLoads();
558
559 doLoadCallbacks(results, cols);
Here is a test for the code above, I think it only works with mysql,
because other dbms have support for foreign key constraints and will
delete Glarch g if I delete Glarch g2. I am right?
protected void testIdNotFound(SessionFactory sessions) throws Exception
{
//The following test is only enabled for MySQL which has no foreign
key constraints.
if (db.equals("mysql")) {
Session s = sessions.openSession();
Glarch g = (Glarch) s.create(Glarch.class);
Glarch g2 = (Glarch) s.create(Glarch.class);
g.setNext(g2);
Serializable gid = s.getID(g);
Serializable g2id = s.getID(g2);
s.commit();
s = sessions.openSession();
g2 = (Glarch) s.load( Glarch.class, g2id );
s.delete(g2);
s.commit();
s = sessions.openSession();
boolean ok = false;
try {
g = (Glarch) s.load( Glarch.class, gid );
}
catch (HibernateException e) {
ok = "id not found or provided object was wrong
class".equals(e.getMessage());
}
catch (java.lang.StackOverflowError soe) {
ok = false;
}
assert( ok, "id not found");
s.commit();
}
}
P.S.:
build.xml lacks the exclusion of the build directory and the build.xml
file. If you are lazy and build without doing "ant clean" before, the
build-directory is recursively copied in the build-directory ...
The two exclude Tags fix it:
32 <patternset id="support.files">
33 <include name="**/*.properties"/>
34 <include name="**/*.dtd"/>
35 <include name="**/*.xml"/>
36 <exclude name="build/**/*"/>
37 <exclude name="build.xml"/>
38 </patternset>
|