Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to define an inverse cascade delete on a many-to-one mapping in hibernate

I have two classes A and B. Many B's can have association with a single A, hence a many-to-one relationship from B to A. I've mapped the relationship like:

<class name="A" table="tbl_A">
  <property name="propA" column="colA"/>
</class>
<class name="B" table="tbl_B">
  <property name="propB" column="colB"/>
  <many-to-one name="a" class="A" column="col1" cascade="delete"/>
</class>

A has nothing mapped to B. Keeping this in mind we intend to delete B when it's associated A is deleted. This could have been possible if I could define an inverse="true" on the many-to-one association in B but hibernate does not allow that.

Can anyone help with this? We do not want to write anything in A for this.

like image 372
Monis Iqbal Avatar asked Nov 11 '09 13:11

Monis Iqbal


People also ask

What is difference between Cascade and inverse in Hibernate?

The property “Cascade” is used to define if update/delete method that applies to one object equally applies to a related one. “inverse”, however, is a property that defines which object is responsible for maintaining the relationship with another object.

What is Cascade delete in Hibernate?

When you now remove an Author entity, Hibernate cascades the operation to all associated Book entities. From there, it cascades it to all associated Authors and from there to their Books and so on. So, in this example, Hibernate will cascade the remove operation from Author 1 to Book 1 and 2.

What is reverse mapping in Hibernate?

To govern this process Hibernate™ uses a reverse engineering strategy. A reverse engineering strategy is mainly called to provide more Java like names for tables, column and foreign keys into classes, properties and associations. It is also used to provide mappings from SQL types to Hibernate™ types.

What is inverse attribute in Hibernate?

An Inverse attribute is used to maintain the relationship between the parent and child class object. The inverse attribute is used only with bi-directional mappings such as one-to-many and many-to-many Hibernate mapping.


1 Answers

Hibernate only cascades along the defined associations. If A knows nothing about Bs, nothing you do with A will affect Bs.

Pascal's suggestion is, therefore, the easiest way to do what you want:

<class name="A" table="tbl_A">
  ...
  <set name="myBs" inverse="true" cascade="all,delete-orphan">
    <key column="col1"/>
    <one-to-many class="B"/>
  </set>
</class>

<class name="B" table="tbl_B">
  ...
  <many-to-one name="a" class="A" column="col1" not-null="true"/>
</class>

Note that setting cascade="delete" on B as you have it in your original code will NOT do what you want - it tells Hibernate to "delete A if B is deleted" which is likely to result in constraint violation (if there are any other Bs linked to that A).

If you absolutely cannot add a collection of Bs to A (though I can't really think of the circumstances where that'd be the case), your only other alternative is to define cascade delete from A to B at the foreign key level; your Bs will then be deleted when your A is deleted.

This is a rather ugly solution, however, because you have to be extremely careful of how you delete A in Hibernate:

  1. Session must be flushed prior to deleting A (having pending updates to B may result in an error or A and some Bs being re-inserted behind the scenes)
  2. All Bs linked to your A (and since you're not maintaining the relationship from A side that means all Bs) must be evicted from all active sessions and 2nd level cache.
like image 137
ChssPly76 Avatar answered Sep 27 '22 22:09

ChssPly76