What would be the right and easy way to update the collection if it's mapped with all-delete-orphan by it's "parent" object?
By updating I don't mean just adding/removing items from collection, but also updating the values of item properties (of course for those items that were previously in the collection).
Scenario is there's a Parent object that has a collections of Child objects and there's one form by which users can edit the Children collection - add/remove children but also edit the children's properties (on the same form).
Basically I want something like this:
Parent parent = session.get(Parent.class, parentUI.getId());
parent.setChildren(parentUI.getChildren()); // parentUI is a DTO
session.saveOrUpdate(parent);
This doesn't work and I understand the reasons why, but as it seems to me this should be a very common situation when using hibernate and developing UI applications, so I'm seeking for a (by the book) solution.
I'm using hibernate 3.6.10 and XML based configuration.
Here's the relevant mapping (I'm using ArrayList for storing children collection):
<list name="children" cascade="all, delete-orphan">
<key column="parent_id" not-null="true"/>
<list-index column="ordinal" />
<one-to-many class="Child" />
</list>
If it matters child objects also have collections mapped in the same way but I don't think it's relevant since that is a problem equal to the one described.
Btw. I've lost a whole day on this and of course checked tens of very similar questions to this, but haven't found a reasonable solution or a pattern for solving this. Perhaps I'm missing something?
Well since I didn't find a by the book solution I've first solved this manually by creating a custom method on my parent object
parent.updateChildren(parentUI.getChildren())which iterates through the old collection, compares it to the updated one from the UI and updates it manually. Needless to say it's far from ideal.Then a colleague of mine (Zoran Regvart) gave me an witty idea (considering the technologies I'm using ie. Spring MVC) for improving things a little.
Idea is that, in case of submitting a form which updates the parent, before spring (web) binder does his work we can load the collection from the DB and set it to the command object (
parentUI) thus "planting" it to be updated by the spring binder (in other words delegating the collection update process to him - thing that he does anyways).Here is the (pseudo)code:
This way when spring binder does his work he will be updating the collection that is already bounded to Hibernate session.
This solution also isn't something that I'm too happy with and I haven't tested in many scenarios but for my current needs (for me) it's certainly somewhat of an improvement.
UPDATE: this workaround is convenient only in the case of adding new children or editing their properties. For cases of deleting children or changing their order it better avoided since it ads complexity.