8

I'm still not very clear about the way cascade works in deletion operations. I was wondering what happens if I have this:

class myBean{

    @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
        public Cliente getClienteDiAppartenenza() {
            return clienteDiAppartenenza;
        }

}


class Cliente{
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true, fetch = FetchType.LAZY)
    public List<myBean> getMyBeans() {
        return myBeans;
    }
}

if I delete the myBean with this property I'm not sure if the linked Cliente will be deleted too (weird in a manytoone) or the collection inside Cliente will be updated and that instance of myBean removed, then saved.

What will happen?? Hibernato docs aren't very clear about this...

digitaljoel
  • 26,265
  • 15
  • 89
  • 115
gotch4
  • 13,093
  • 29
  • 107
  • 170

2 Answers2

20

This is not a Hibernate thing, this is part of the JPA 2.0 standard. You have two aspects in your annotations, one thing is the use of orphanRemoval.

You use orphanRemoval when the parent entity has control over the creation and destruction of the child entity. In UML this would be a case of composition that is a strong ownership and concident lifetime of the parts by the whole. The JPA 2.0 specification in section 2.9: Entity Relationships says:

Associations that are specified as OneToOne or OneToMany support use of the orphanRemoval option. The following behaviors apply when orphanRemoval is in effect:

  1. If an entity that is the target of the relationship is removed from the relationship (by setting the relationship to null or removing the entity from the relationship collection), the remove operation will be applied to the entity being orphaned. The remove operation is applied at the time of the flush operation. The orphanRemoval functionality is intended for entities that are privately "owned" by their parent entity. Portable applications must otherwise not depend upon a specific order of removal, and must not reassign an entity that has been orphaned to another relationship or otherwise attempt to persist it. If the entity being orphaned is a detached, new, or removed entity, the semantics of orphanRemoval do not apply.

  2. If the remove operation is applied to a managed source entity, the remove operation will be cascaded to the relationship target in accordance with the rules of section 3.2.3, (and hence it is not necessary to specify cascade=REMOVE for the relationship)[20].

A second aspect would be the use of cascase=REMOVE when no orphanRemoval is implied.

The section 3.2.3: Removal contains details about the remove process:

The semantics of the remove operation, applied to an entity X are as follows:

• If X is a new entity, it is ignored by the remove operation. However, the remove operation is cascaded to entities referenced by X, if the relationship from X to these other entities is annotated with the cascade=REMOVE or cascade=ALL annotation element value.

• If X is a managed entity, the remove operation causes it to become removed. The remove operation is cascaded to entities referenced by X, if the relationships from X to these other entities is annotated with the cascade=REMOVE or cascade=ALL annotation element value.

• If X is a detached entity, an IllegalArgumentException will be thrown by the remove operation (or the transaction commit will fail).

• If X is a removed entity, it is ignored by the remove operation.

A removed entity X will be removed from the database at or before transaction commit or as a result of the flush operation. After an entity has been removed, its state (except for generated state) will be that of the entity at the point at which the remove operation was called.

Edwin Dalorzo
  • 76,803
  • 25
  • 144
  • 205
  • Thanks for your effort, but this relates more to the bean that has the collection and not bean that is INSIDE it... maybe I misunderstood.. – gotch4 May 31 '11 at 16:01
  • @gotcha4 You certainly misunderstood. Point #2 in the first quote up there covers that case, as well as the the second bullet in the second quote I posted. – Edwin Dalorzo May 31 '11 at 16:51
  • Then I should expect that the bean holding the collection will be updated on DB, without the managed entity being removed (if cascaded of course)? Well.. this doesn't work. – gotch4 Jun 01 '11 at 14:17
1

Your JPA provider isn't going to manage your java collections in memory for you. If you have a relationship mapped in both sides, then one side should be defined as the owning side using the mappedBy attribute in the mapping of the non-owning side. It's up to you to decide which side is the owning side. Once you've made that decision, the JPA provider will keep things up to date in the database using whatever cascade/orphan management you've defined in the mapping but you are left to manage your collections in the non-owning side.

One way to manage this is to have a service method that is used to make the change and that service method takes care of updating the collection or the reference in your 1-n and n-1 side of things so your java objects are correct in memory.

digitaljoel
  • 26,265
  • 15
  • 89
  • 115
  • There is no decision regarding ownership of this relation, as for ManyToOne associations, the many-side must be the owner, at least for the current version of JPA (2.1) -- this may change in future versions. – Dominik Oct 31 '16 at 22:09