Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to delete bidirectional many-to-many association

Problem:

I have many-to-many association between two entities A and B. I set A entity as an owner of their relationship(inverse=true is on A's collection in b.hbm.xml).

When i delete an A entity, corresponding records in join table are deleted.
When i delete an B entity, corresponding records in join table are not deleted (integrity violation exception).

--

Let's consider some very simple example:

class A{  
    Set<B> bset=new HashSet<B>();
    //...
}  

class B{  
    Set<A> aset=new HashSet<A>();  
    //...
}

File a.hbm.xml [m-to-m mappings only]:

<set name="bset" table="AB">  
    <key name="a_id"/>  
    <many-to-many column="b_id" class="B"/>  
</set>

File b.hbm.xml [m-to-m mappings only]:

<set name="aset" table="AB" inverse="true">  
    <key name="b_id"/>  
    <many-to-many column="a_id" class="A"/>  
</set>

Database relations:

A(id,...)  
B(id,...)  
AB(a_id,b_id)

Suppose that we have some records in AB joint table. For example:

AB = {(1,1),(1,2)}

where AB= { (a_id , b_id) | ... ... }

--

Situation 1 - works probably because A is owner of AB relationship:

A a=aDao.read(1);  //read A entity with id=1  
aDao.delete(a);    //delete 'a' entity and both relations with B-entities

Situation 2 - doesn't work:

B b=bDao.read(1);   //read B entity with id=1  
bDao.delete(b);     //foreign key integrity violation

On the one hand, this is somehow logical to me, because the A entity is responsible for his relation with B. But, on the other hand, it is not logical or at least it is not orm-like solution that I have to explicitly delete all records in join table where concrete B entity appears, and then to delete the B entity, as I show in situation 3:

Situation 3 - works, but it is not 'elegant':

B b=bDao.read(1);  
Set<A> aset=b.getA();     //get set with A entities
Iterator i=aset.iterator();  

//while removes 'b' from all related A entities  
//while breaks relationships on A-side of relation (A is owner)
while(i.hasNext()){  
    A a=i.next();  
    a.bset.remove(b);   //remove entity 'b' from  related 'a' entity 
    aDao.update(a);       //key point!!! this line breaks relation in database
}  
bDao.delete(b);           //'b' is deleted because there is no related A-entities

--

So, my question: is there any more convenient way to delete no-owner entity (B in my example) in bidirectional many-to-many association and all of his many-to-many relations from joint table?

like image 485
slomir Avatar asked Apr 27 '11 21:04

slomir


People also ask

Is many to many bidirectional?

In JPA we use the @ManyToMany annotation to model many-to-many relationships. This type of relationship can be unidirectional or bidirectional: In a unidirectional relationship only one entity in the relationship points the other. In a bidirectional relationship both entities point to each other.


1 Answers

I do not see what is not elegant about the code. It works fine in all cases and does not do any extra stuff which it is not supposed to. When I say A is owning side is a relationship AB, this would imply that creating or deleting the relationship lies in the hands of A. B has no say in the relationship. So if I want to move B somewhere else, A has to let go of B before B can be moved away. Hence, when choosing the owning side you should consider what you are going to do with the objects.

like image 183
Satadru Biswas Avatar answered Nov 12 '22 15:11

Satadru Biswas