]
Robert Nice commented on HHH-2498:
----------------------------------
This is almost certainly some strange bug.
If you call remove on such a regular lazy collection before otherwise touching it, there
is one operation assigned to a DelayedOperation class. It either never gets run, or the
index cannot be looked up because initialization changes the index object. The example
above uses a long, so I doubt that's it.
My solution was to simply mark the collection as extra lazy as this takes a different code
path, otherwise get the object before removing it; but there's certainly something
funky going on. I'll try and reproduce a test case.
Lazy Inverse Map Bug?
---------------------
Key: HHH-2498
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-2498
Project: Hibernate Core
Issue Type: Bug
Affects Versions: 3.2.1, 3.2.2
Environment: Hibernate 3.2.2, Java5, MySQL 5 (InnoDB)
Reporter: CannonBall
Priority: Minor
Mapping documents:
<hibernate-mapping>
<class name="scratchpad.hibernate.A">
<id name="id">
<generator class="assigned"/>
</id>
<map name="bs" cascade="all-delete-orphan"
inverse="true">
<key column="aId"/>
<map-key type="long" column="cId"/>
<one-to-many class="scratchpad.hibernate.B"/>
</map>
</class>
<class name="scratchpad.hibernate.B">
<id name="id">
<generator class="assigned"/>
</id>
<many-to-one name="a" class="scratchpad.hibernate.A"
column="aId"/>
<many-to-one name="c" class="scratchpad.hibernate.C"
column="cId" not-null="true"/>
</class>
<class name="scratchpad.hibernate.C">
<id name="id">
<generator class="assigned"/>
</id>
</class>
</hibernate-mapping>
Code between sessionFactory.openSession() and session.close():
long aId = 1l;
long bId = 2l;
long cId = 3l;
SessionFactory factory = new Configuration().configure()
.buildSessionFactory();
try {
Session s = factory.openSession();
try {
Transaction tx = s.beginTransaction();
try {
C c = new C(cId);
s.save(c);
A a = new A(aId);
B b = new B(bId);
b.setC(c);
b.setA(a);
a.getBs().put(cId, b);
s.save(a);
tx.commit();
} catch (Exception e) {
try {
tx.rollback();
} catch (Exception e2) {
// do nothing
}
throw e;
}
} finally {
s.close();
}
s = factory.openSession();
try {
Transaction tx = s.beginTransaction();
try {
A a = (A) s.load(A.class, aId);
a.getBs().remove(cId);
tx.commit();
} catch (Exception e) {
try {
tx.rollback();
} catch (Exception e2) {
// do nothing
}
throw e;
}
} finally {
s.close();
}
} finally {
factory.close();
}
Name and version of the database you are using: MySQL 5.0.33
The generated SQL (show_sql=true):
Hibernate: select b_.id, b_.aId as aId1_, b_.cId as cId1_ from B b_ where b_.id=?
Hibernate: insert into C (id) values (?)
Hibernate: insert into A (id) values (?)
Hibernate: insert into B (aId, cId, id) values (?, ?, ?)
Hibernate: select a0_.id as id0_0_ from A a0_ where a0_.id=?
Hibernate: select bs0_.aId as aId1_, bs0_.id as id1_, bs0_.cId as cId1_, bs0_.id as
id1_0_, bs0_.aId as aId1_0_, bs0_.cId as cId1_0_ from B bs0_ where bs0_.aId=?
I've been having a confusing problem shown above, whereby A has a Map of Bs indexed
using the id from an association with C. This Map is inversely mapped for A and with
'Cascade Delete Orphan'. In the second opened session above, where B is removed
from A's Map and thus orphaned, B will not be deleted. I have observed B is only
deleted if I either set 'lazy="false"' for A's Map or make an
interaction with A's Map in the code (before B's removal) like
'a.getBs().get(cId)'. I suspect the lazy intializer is not initializing correctly
in the above scenario.
The above scenario does not happen if A's Map is not inversely mapped but B's
many-to-one with A is.
Can somebody shed some light on whether this is me using Hibernate incorrectly or is a
bug?
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: