2012-10-12 3 views
2

Je reçois un primaryKeyUpdateDisallowed ValidationException lorsque j'essaie de fusionner une entité dans la base de données lorsqu'il existe une entité existante avec la même clé primaire.JPA EntityManager Merge Exception

Bien sûr, je n'obtiens pas l'exception lorsque j'effectue un TypedQuery et que le gestionnaire d'entités renvoie l'entité en premier, met à jour les valeurs appropriées, puis fusionne. Le problème est que ce processus est trop coûteux, en termes de ressources. Je dois pouvoir fusionner simplement sans l'exception résultante.

Existe-t-il un moyen de structurer notre classe d'entité afin que nous puissions écraser les enregistrements, y compris les clés primaires? Ou d'une autre manière autour du problème?

+0

Montrez-nous votre code. Cette exception indique que vous essayez de modifier la valeur du PK d'une entité persistante, ce qui est interdit. –

Répondre

0

En JPA, si vous souhaitez faire:

entityManager.merge(someEntity); 

alors vous devez d'abord avoir someEntity chargé de la DB dans le contexte de persistance de entityManager puis détaché par « entityManager.detach (someEntity) » ou par compensation le contexte de persistance. Si someEntity n'est pas préchargé et détaché, mais créé à la place via "new SomeEntity()", la fonction merge() déterminera que vous avez ajouté une nouvelle entité et que vous effectuerez une opération interne très similaire à entityManager.persist (someEntity). Lorsque les données sont vidées ou validées dans une transaction, il génère un INSERT SQL, qui va entrer en conflit avec le PK préexistant.

Voici le comportement spécifié de la spécification JPA 2:


La sémantique de l'opération de fusion appliquée à une entité X sont les suivants:

  • Si X est un détaché entité, l'état de X est copié sur une instance d'entité gérée préexistante X 'de la même identité ou une nouvelle copie gérée X' de X est créée. Si X est une nouvelle instance d'entité, une nouvelle instance d'entité gérée X 'est créée et l'état de X est copié dans la nouvelle instance d'entité gérée X'.

> Le problème est ce processus est trop cher, les ressources sage. Je dois pouvoir fusionner simplement sans l'exception résultante.

Cela ne devrait pas être le cas. Récupérer l'entité ou la liste d'entités de la base de données devrait être efficace. Peut-être que votre requête pourrait être améliorée. Avez-vous une clause "where" sur la requête? Avez-vous beaucoup de cascades d'entités lors de l'actualisation (via l'attribut cascade = CascadeType.REFRESH/ALL sur les relations telles que @OneToMany ou @ManyToOne)? Avez-vous une hiérarchie d'héritage très complexe avec de nombreuses entités/tables? Si vous pouviez fournir votre requête JPQL ou critère, je suis sûr que le problème sera simple à résoudre. :-)

Questions connexes