2

I have a problem with Hibernate.

In Short:

How to configure a ManyToMany association with Hibernate when the relationship has an attribute and we need save, delete and update in cascade?

In Large:

Imagine the following DataBase:

             Super      Mini
                 M______N
                     |
                     attribute

There are 3 tables here:

"Mini", "Super" and "Super_Mini".

Now imagine Super_Mini has 1 attribute for the relation (and obviously the keys).

Ok, now this is translating to Hibernate by the following:

 Super:
 // The relation is Many to Many, but considering that it has an attribute, this is OneToMany with the ManyMany RelationShip
 @OneToMany(mappedBy="mini", targetEntity=Mini.class)   
 @Cascade({CascadeType.SAVE_UPDATE, CascadeType.DELETE})    
 @LazyCollection(LazyCollectionOption.TRUE)
 private Set<SuperMini> superMini = new HashSet<SuperMini>();


 SuperMini:
 @Id    
 @ManyToOne(targetEntity=Super.class,fetch=FetchType.LAZY)  
 @Cascade({CascadeType.LOCK})   
 @JoinColumns({ @JoinColumn(name="...", referencedColumnName="...") })  
 private Super super;   

 @Id    
 @ManyToOne(targetEntity=Mini.class,fetch=FetchType.LAZY)   
 @Cascade({CascadeType.LOCK})   
 @JoinColumns({ @JoinColumn(name="...", referencedColumnName="...") })  
 private Mini mini;

So, I think the configuration is correct, and the save, independently if the object has Mini childrens save all of them. The problem is when I try to delete the object:

 Super data = getHibernateTemplate().load(Super.class, idSuper);

 getHibernateTemplate().getSessionFactory().getCurrentSession().clear();

 data.setMini( new HashSet<Mini>() );

 getHibernateTemplate().delete( data );
 getHibernateTemplate().getSessionFactory().getCurrentSession().flush();

Hibernate don´t delete the Mini relation... What´s the problem? I know how to solve it by HQL, but maybe the configuration is not correct, I don´t know.

Thank you in advance,

ganzux
  • 874
  • 3
  • 15
  • 35

1 Answers1

1

Your question is not clear. Super does not contain a Set<Mini2>. It contains a Set<SuperMini2>. So the last code snippet doesn't make much sense.

Moreover, the targetEntity attribute on Super.superMini2 is incorrect, and unnecessary.

CascadeType.ALL include CascadeType.DELETE, so it's also unnecessary.

But to answer your question, I think the problem is that deleting Super cascades to SuperMini2 because the association has a cascade delete, but there is no cascade delete between SuperMini2 and Mini2, so of course, Mini2 instances are not deleted.

EDIT:

The answer is that the OP, before editing the question, removed all the entities from the collection of SuperMini before deleting the Super entity. So the cascade delete on the collection of Supermini didn't have anything to delete anymore.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thanks for your answer. Super does not contain a Set because the relation between Super and Mini2 has an attributte. When I delete a Super, the relation between Super and Mini2 (the relation, not the Entity Mini2) must be deleted. – ganzux Dec 16 '11 at 12:07
  • **@JB Nizet**, I have added the next comment to the original Thread: // The relation is Many to Many, but considering that it has an attribute, this is OneToMany with the ManyMany RelationShip – ganzux Dec 16 '11 at 12:27
  • Please show us the real code used to delete the Super entity. Do you really have those data.setMini2'new HashSet()) in your code. What does this call do? Why do you do it? – JB Nizet Dec 16 '11 at 13:49
  • To remove the Entity Super with the dependences I use the code pasted up, this is the real code. I set empty collections for using the hibernate cascade deletes. I think the problem is that the class SuperMini2 has the tag @Id in the ManyToOne relation... But no idea :?. Thanks again – ganzux Dec 16 '11 at 13:51
  • I had simplify the question, but I don't know the answer yet :? – ganzux Dec 19 '11 at 08:28
  • Cascade delete means: when deleting this entity, also delete all the entities in this collection. You're removing the entities from the collection, and then delete the entity, so Hibernate cascade the delete on all the entities in the collection, but there isn't any entity anymore since you just removed them. And I still don't understand how you can have a setMini(Set) method is Super, since Super doesn't have any association with Mini. It has an association with SuperMini (or SuperMini2, I don't know anymore because your post is self-contradictory) – JB Nizet Dec 19 '11 at 09:14
  • Thanks for your answer. I have a Super entity with ManyToMany relationship with Mini entity; this relation has an atributte. In Hibernate this is traslating to a OneToMany and ManyToOne relations (read H. FAQs "I have a many-to-many association between two tables, but the association table has some extra columns (apart from the foreign keys). What kind of mapping should I use?" http://community.jboss.org/wiki/HibernateFAQ-TipsAndTricks). So this is correct. Problably you're right in setting the collection of Mini as an empty collection is not necesary, but that´s not the problem. Thanks again. – ganzux Dec 19 '11 at 10:45
  • That **IS** the problem. See my comment to your answer. You told me n times that you couldn't have a many-to-many to Mini because of the additional attribute. And I know that. Yet, you made a call (in the previous version of your question) to a method setMini(Set). Do you realize it makes no sense, and the setter should be setSuperMinis(Set)? – JB Nizet Dec 19 '11 at 11:04
  • Ok, that´s correct, but if I remove the setter to an empty collection, don´t launch the delete HQL, don´t works. I agree with you that this line was not correct. – ganzux Dec 19 '11 at 11:13
  • And that's precisely what I explained you just before: Cascade delete means: when deleting this entity, also delete all the entities in this collection. You're removing the entities from the collection, and then delete the entity, so Hibernate cascade the delete on all the entities in the collection, but **there isn't any entity anymore since you just removed them**. Instead of answering to your own question with an incorrect answer, you should upvote my answer, and accept it once I've edited it to put in the answer what I discovered after this looong conversation with you. – JB Nizet Dec 19 '11 at 11:18
  • Ok, I have test it and works too. Finally I set it as a TRUE Lazy loading and the Cascade SAVE_UPDATE and DELETE. Thanks **JB Nizet**, now I understand a little more Hibernate :) – ganzux Dec 19 '11 at 11:31
  • Hm... Now the saveOrUpdate doesn´t work... First it must do the delete of the collection and then the inserts, but only do the inserts... What´s the problem? Thanks – ganzux Dec 20 '11 at 12:04
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/6003/discussion-between-ganzux-and-jb-nizet) – ganzux Dec 20 '11 at 12:26