Issue Type: Bug Bug
Affects Versions: 4.1.8
Assignee: Unassigned
Components: core
Created: 18/Jan/13 5:29 PM
Description:

The problem seems to be that no matter what sort of concurent-safe collection one uses to implement a mapped collection, Hibernate's internal cascade mechanism uses a HashSet when cascading; This breaks a typical design pattern used for consistency:

To replicate:

inside A.java
...
@OneToMany(mappedBy = "myA", cascade=CascadeType.ALL)
private Set<B> myBs = new CopyOnWriteArraySet<B>();
// methods getMyBs and setMyBs don't do anything special
inside B.java
@ManyToOne
private A myA;

// Typical bidirectional integrity maintenance method
public void setMyA(A newA) {
   //.. various tests not shown
   if (this.myA != null) { 
        this.myA.getMyBs().remove(this);
      }
   if (newA) != null) {
      newA.getMyBs().add(this);
      }
   this.myA = newA;
}

...
// Clean Up on preRemove
@PreRemove
public void preRemove() {
  this.setMyA(null);
}

Now, if somebody tries to remove an instance of a B, the preRemove method causes the parent A to delete that B from its set myBs. Just what is wanted.

If someone tries to remove an A, the remove will cascade to all the elements of myBs, also as desired. But when this cascaded removal of the B encounters the preRemove code and tries to remove itself from the A, we get a concurrent access violation. Stack trace shows that in spite of the field myBs being defined as a concurrent-safe class, Hibernate is internally using a hashMap to do the cascade.

Environment: 4.1.8 on Postgres
Project: Hibernate ORM
Priority: Major Major
Reporter: Chris Owens
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira