Add entity in one-to-many collection, auto-flush and remove entity does not remove the
entity
---------------------------------------------------------------------------------------------
Key: HHH-3354
URL:
http://opensource.atlassian.com/projects/hibernate/browse/HHH-3354
Project: Hibernate3
Issue Type: Bug
Components: core
Affects Versions: 3.2.1
Environment: Observed on MySQL 5, unit tested on HSQLDB.
Reporter: Pascal Perez
Attachments: entities.zip
In plain English:
An Item may have multiple Comment (one-to-many). When adding two comments to an item,
auto-flushing, and removing one item, Hibernate loses track of both comments and does not
delete the removed comment. The cascading has "delete-orphan".
Hibernate behaves in two different ways depending on whether the removed comment entity
holds a reference to the Item or not.
1) if it holds a reference: the Comment entity is not removed. The transaction commits
silently.
2) if it does not hold a reference anymore (i.e. comment.item = null): The Comment entity
is updated to have it's reference to Item set to NULL, but is not deleted. This
creates zombie entities in the DB. This case is highlighted in the unit test below by
forcing the relation to be not-null="true" triggering a DB constraint violation
upon commit. Otherwise, Hibernate commits silently.
In unit tests (test is parameterized to handle cases 1 and 2):
@Test
public void addAutoFlushRemove() throws Exception {
autoFlushInTheMiddle(false);
}
@Test
public void addAutoFlushUnreferenceRemove() throws Exception {
autoFlushInTheMiddle(true);
}
private void autoFlushInTheMiddle(boolean commentToItemReference) {
// creating an item
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Item item = new Item();
session.save(item);
assertEquals(0, item.comments.size());
tx.commit();
session.close();
// reading back the item, add two comments, auto-flush, delete one
session = sessionFactory.openSession();
tx = session.beginTransaction();
item = (Item) session.get(Item.class, item.id);
Comment comment1 = new Comment(); comment1.item = item;
item.comments.add(comment1);
Comment comment2 = new Comment(); comment2.item = item;
item.comments.add(comment2);
// forcing an auto flush
session.createCriteria(Item.class).list();
item.comments.remove(comment1);
if (commentToItemReference) comment1.item = null;
tx.commit();
session.close();
// check that we have one comment
session = sessionFactory.openSession();
item = (Item) session.get(Item.class, item.id);
assertEquals(1, item.comments.size());
session.close();
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://opensource.atlassian.com/projects/hibernate/secure/Administrators....
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira