2010-08-22 4 views
5

J'ai une entité qui contient deux autres entités avec une relation @ManyToOne.Hibernate et NonUniqueObjectException

@Entity 
public class A extends Serializable{ 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    private Long id; 

    @ManyToOne 
    @Cascade(CascadeType.SAVE_UPDATE) 
    private B b; 

    @ManyToOne 
    @Cascade(CascadeType.SAVE_UPDATE) 
    private C c; 

} 

Si je tente de sauver une Une instance qui ont « B_ID » et « C_Id » d'un autre Un dossier que je reçois l'exception:

org.hibernate.NonUniqueObjectException: un objet différent avec le même valeur d'identifiant a déjà été associé à la session

par exemple:

A table 
| ID | B_ID | C_ID | 
| 1 |  1 | null | // this works 
| 2 | null |  1 | // this works 
| 3 |  1 |  x | // this throws the exception 
| 4 |  x |  1 | // this throws the exception 

x=any value of existent B/C_ID 

B_ID et C_ID ne sont pas uniques dans mon modèle et (B_ID + C_ID) n'est pas une contrainte unique !!

Que puis-je faire?

Merci d'avance.

Répondre

15

Hibernate ne se plaint pas de l'unicité de la base de données ici, il se plaint que le Session actuel contient déjà un objet avec le même ID qu'un nouvel objet que vous essayez d'enregistrer. Il ne permettra pas cela - Hibernate a une exigence stricte qu'un ID donné ne peut pas être représenté par deux objets différents dans le cadre d'une seule session. À un certain point, votre application a enregistré dor charger une entité avec ce même ID, et cet objet est déjà "enregistré" avec la session. Il est difficile de dire dans ce cas précis quel ID il se plaint, puisque le texte d'exception n'est pas clair. Essayez de supprimer temporairement les directives en cascade et voyez si cela arrive encore, essayez de le réduire. Si nécessaire, vous pouvez forcer la session à «oublier» tous les objets existants pour un ID donné (en utilisant Session.evict() dans l'API Hibernate ou EntityManager.detach() dans l'API JPA 2.0), mais ce n'est pas une solution très élégante. Pour réitérer - cette exception n'a rien à voir avec les contraintes de la base de données, il s'agit de protéger Hibernate la cohérence de son état interne en mémoire.

+0

Merci, les seules choses que je charge de DB sont B et C, et je les utilise dans un objet. Mais B et C ont CascadeType.SAVE_UPDATE, donc ils ne sont pas sauvegardés à nouveau, mais seulement mettre à jour ... j'espère ... – blow

+0

Les problèmes sont aussi au démarrage, quand la session est nouvelle. – blow

+0

enlever les directives en cascade fonctionne bien, mais ... POURQUOI ??? Sans "Cascade.SAVE_UPDATE" hibernate devrait essayer de re-SAVE "A" et "B" qui sont déjà présents dans DB et donc jeter une exception, mais cela fonctionne à la place ... pourquoi? – blow