]
Michael Cameron updated HHH-7122:
---------------------------------
Attachment: stacktrace.txt
Stack trace attached. However, as I mentioned, the stack trace will just highlight the
proximate issue. Fixing that problem so it uses the correct persister for the child class
will only cause another problem when it tries to execute the delete action on the second
and later flushes. The root problem is the loadedState of the parent does not change when
the cascade delete occurs on the child.
one-to-one with cascading delete of orphans causes
IllegalArugmentException
---------------------------------------------------------------------------
Key: HHH-7122
URL:
https://hibernate.onjira.com/browse/HHH-7122
Project: Hibernate ORM
Issue Type: Bug
Components: core
Affects Versions: 3.6.10, 4.1.0
Environment: Hibenate 3.6.x, 4.1.x (probably all since HHH-4726, but only tested
on 3.6 and master branches)
Reporter: Michael Cameron
Priority: Critical
Labels: core, one-to-one, orphan-removal
Attachments: hibernate-3.6-test-patch.diff, hibernate-master-test-patch.diff,
stacktrace.txt
Hibernate does not handle cascading deletes of orphans one-to-one properties.
For example in the following relationship:
{code:xml}
<class name="Employee">
<id name="id" type="long" column="id">
<generator class="increment" />
</id>
<one-to-one name="info"
property-ref="employee"
class="EmployeeInfo"
cascade="all,delete-orphan"
constrained="false" />
</class>
<class name="EmployeeInfo">
<id name="id" type="long" column="id">
<generator class="increment" />
</id>
<many-to-one name="employee"
column="employee_id"
unique="true"
not-null="true" />
</class>
{code}
If you retrieve an Employee with an EmployeeInfo from the DB, then set the employee.info
to null, the first flush will correctly delete the orphan, but every flush after that in
the same session will fail with an Illegal Argument Exception:
{{java.lang.IllegalArgumentException: object is not an instance of declaring class}}
I've researched the issue about as far as I can take it. The initial proximate case
is that {{Cascade.cascadeProperty}} gets the entity name of the parent to pass on to the
delete action. On the second call to flush, the value has been deleted, so it uses the
entity name to look up the persister in {{DefaultDeleteEventListener.deleteEntity}}. It
uses that persister to try to get the ID, but that's the persister of the parent class
to get the ID of the child class, which fails with the exception above. I tried passing
{{null}} in as the entityName so it would look up the persister using just the object, but
that fails because then the delete has nothing to delete (it actually has been deleted
already). That helped me understand the issue better.
In this case, the loadedState of the parent remains in place after the cascaded delete of
the child because none of it's direct properties changes. So after the initial flush
with the delete of the child, the next flush will still find the child object in the
loaded state, but it is no longer in the session's persistence context, and it fails
with the IllegalArgumentException above.
I don't know the hibernate internals above, so I don't know if the direct
solution I'm thinking of would work: update the loaded state of the parent in
{{Cascade.cascadeProperty}} after it calls {{eventSource.delete}}. Is this too direct?
Does it need to happen with the action queue is actually executed? Is there enough
information upon execution of this child to update the parent like EntityInsertAction and
EntityUpdateAction?
I've attached patch files the 3.6 and master branch with tests that fail because of
this issue. I wouldn't mind making changes to fix the problem and submitting a pull
request, but I'll need guidance on how to approach it.
--
This message is automatically generated by JIRA.
For more information on JIRA, see: