I'm sorry I can only theorize as to why the inserts are run however I do know that your problem is probably caused by updating the elements in a set in such a way the the hashcode and equals of these elements is affected.
This is from the java.util.Set javadoc
http://java.sun.com/javase/6/docs/api/java/util/Set.html
"Note: Great care must be exercised if mutable objects are used as set elements.
The behavior of a set is not specified if the value of an object is changed in a manner that affects equals comparisons while the object is an element in the set."
In the code you submitted you have changed the value of the name property. As the name property is used to determine the hashCode of the child object the set no longer works as you expect.
To demonstrate this consider the following code:
Code:
if(p.getChildren() != null) {
int counter = 4;
for(Child c : p.getChildren()) {
System.out.println(p.getChildren().contains(c));
c.setName("c"+counter);
System.out.println(p.getChildren().contains(c));
counter++;
}
}
I would expect this program to output (for the three children in your example)
Code:
true
false
true
false
true
false
So what is happening here? Well during each iteration of the loop the name property of each element is changed. Changing the name property affects the hashcode of the element in such a way that the Set p.getChildren() starts to think it doesn't contain this particular element anymore.
A solution may be to remove the element out of the list and then add it back again after the name element has been set. The code to do this could be:
Code:
if(p.getChildren() != null) {
Set<Child> modifiedChildren = new HashSet<Child>();
int counter = 4;
for(Iterator<Child> i = p.getChildren().iterator(); i.hasNext()) {
Child c = i.next();
i.remove();
c.setName("c"+counter);
modifiedChildren.add(c);
counter++;
}
p.getChildren().addAll(modifiedChildren);
}
However this is not very tidy.
A more elegant solution is to base the hashcode and equals off the id of the child and then maybe add some other code to do some validation of the set before you save it. Something like:
Code:
Set<String> childNamesEncounted = new HashSet<String>();
for (Child c : p.getChildren()) {
if (childNamesEncounted.contains(c.getName())) {
throw new RuntimeException("duplicate name entered");
}
}
If you need to do this at the database level then a database constraint should also be implemented (not sure if it is possible to get hibernate to generate this constraint for you - probably faster to implement the constraint yourself).
I hope that helps.