Fusion d'une entité, de changer son id, de fusionner de nouveau, cause “mappé à une colonne de clé primaire dans la base de données. Les mises à jour ne sont pas autorisés” erreur
J'ai un APC programme où EclipseLink est le fournisseur de Persistance. Quand je les fusionner en une entité utilisateur, modifier son ID et tenter de fusionner le même utilisateur instance de nouveau, une erreur est renvoyée. - Je réécrire mon code pour illustrer mon problème de la manière la plus simple.
User user = userManager.find(1);
userManager.merge(user);
System.out.println("User is managed? "+userManager.contains(user);
user.setId(2);
userManager.merge(user);
Le code ci-dessus n'est pas dans un contexte de transaction. userManager est un bean session sans état avec un EntityManager injecté. Lorsqu'il est exécuté, la console imprime:
User is managed? false
Exception [EclipseLink-7251] (Eclipse Persistence Services - 2.1.3.v20110304-r9073): org.eclipse.persistence.exceptions.ValidationException
Exception Description: The attribute [id] of class [demo.model.User] is mapped to a primary key column in the database. Updates are not allowed.
L'exception se produit lors de la deuxième fusion() invocation.
Si je crée un nouvel utilisateur, définit son ID et de fusion, il fonctionne:
User user = userManager.find(1);
userManager.merge(user);
System.out.println("User is managed? "+userManager.contains(user);
User newUser = new User();
newUser.setId(2);
userManager.merge(newUser);
Quelle est donc la différence entre le premier scénario et une seconde? Selon la spécification JPA, tant que l'entité est en état détaché, la fusion doit réussir, non?
(En supposant que l'entité avec l'ID=2)
Pourquoi le EclipseLink fournisseur semble être gêné par le fait que l'entité utilisateur a été fusionnées avant?
Mise à jour: Il semble être un bug de EclipseLink. J'ai remplacé le fournisseur de persistance de EclipseLink de mise en veille prolongée:
- Je changer
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
à
<provider>org.hibernate.ejb.HibernatePersistence</provider>
Aucune erreur n'a été levée.
Oui, c'est une valeur générée
OriginalL'auteur Mingtao Sun | 2012-09-11
Vous devez vous connecter pour publier un commentaire.
La raison en est que la
Id
peut être inséré/défini - comme vous l'êtes dans votre deuxième exemple, mais pas modifié/mis à jour - comme vous lancer dans votre premier exemple. La JPA fournisseur tente de refléter le changement dans la base de données et échoue.JPA 2 spec §2.4 dit
oui, si l'entité n'est pas géré, l'erreur doit se produire sur le
merge
appel, non pas sur lesetId
. Où faut-il se produire? Une chose étrange est que l'entité retournée par l'EM est dit n'est pas gérée. L'EM ne peut que retourner les objets contenus dans le correspondant presistence contexte et donc réussi. Si l'erreur se produit àsetId
, essayez de détacher l'entité explicitement en appelantdetach
ouclear
sur l'EM.L'erreur ne se produisent dans de fusion() au lieu de setId(). Selon l'APC, spec, lorsque l'entité est détaché, il peut être fusionné().
alors je me suis trompé et mon délibérations incorrect. Cela ressemble à un bug. Merci de poster votre solution comme une réponse précisant les versions de EclipseLink et mise en veille prolongée et de l'accepter.
Cela peut avoir été retiré de la version finale de la spécification. Je ne le trouve pas.
OriginalL'auteur kostja
Il semble être un bug de EclipseLink. J'ai changé le fournisseur de persistance de EclipseLink de mise en veille prolongée:
de
à
Aucune erreur n'a été levée.
La version de EclipseLink est 2.3.2. (qui est livré avec la dernière serveur d'application Glassfish 3.1.2).
La version d'hibernate est, dès à présent la dernière, 4.1.7.
OriginalL'auteur Mingtao Sun
Essayer
<property name="eclipselink.weaving.internal" value="false"/>
dans persistence.xml comme parhttp://blogs.nologin.es/rickyepoderi/index.php?/archives/95-Weaving-Problem-in-EclipseLink.html
OriginalL'auteur vnysmnn
Cette réponse est 4 ans de retard, mais quand même.
Vous pouvez la mettre à jour en exécutant régulière requêtes de mise à jour à l'aide de SQL ou JPQL ou Critères API. Je trouve le dernier est le meilleur.
Voici un exemple de code qui peut faire l'affaire. Je l'ai essayé dans une situation similaire et il fonctionne très bien avec EclipseLink.
Au lieu de User_.id vous pouvez passer le nom du champ comme une Chaîne de caractères par exemple "id".
Un autre exemple http://www.thoughts-on-java.org/criteria-updatedelete-easy-way-to/
OriginalL'auteur Theofanis