Hibernate: comment réparer “l’identifiant d’une instance modifiée de X à Y”?

org.hibernate.HibernateException: identifier of an instance of org.cometd.hibernate.User altered from 12 to 3 

En fait, ma table user doit vraiment changer sa valeur de manière dynamic, mon application Java est multithreadée. Des idées comment résoudre ce problème?

Changez-vous la valeur de la clé primaire d’un object User quelque part? Tu ne devrais pas faire ça. Vérifiez que votre correspondance pour la clé primaire est correcte.

À quoi ressemble votre fichier XML de mappage ou vos annotations de mappage?

Vous devez détacher votre entité de la session avant de modifier ses champs d’ID

Dans mon cas, le champ PK dans hbm.xml était de type “entier” mais dans le code bean c’était long .

Dans mon cas, je l’ai résolu en changeant le type de champ @Id de long à long.

Dans mon cas particulier, cela était dû à une méthode dans mon implémentation de service qui nécessitait l’ @Transactional(readOnly = true) spring @Transactional(readOnly = true) . Une fois que j’ai ajouté cela, le problème a été résolu. Inhabituel cependant, c’était juste une déclaration sélective.

Dans mon cas, un modèle avait une faute de frappe, au lieu de vérifier l’équivalence (==), il utilisait une affectation égale (=).

J’ai donc changé la logique du modèle à partir de:

 if (user1.id = user2.id) ... 

à

 if (user1.id == user2.id) ... 

et maintenant tout va bien. Alors, vérifiez également votre sharepoint vue!

Dans mon cas, les getters et les noms de setter étaient différents du nom de la variable.

 private Long stockId; public Long getStockID() { return stockId; } public void setStockID(Long stockID) { this.stockId = stockID; } 

où il devrait être

 public Long getStockId() { return stockId; } public void setStockId(Long stockID) { this.stockId = stockID; } 

Assurez-vous que vous n’essayez pas d’utiliser le même object User plus d’une fois lors de la modification de l’ID. En d’autres termes, si vous faisiez quelque chose dans une opération de type par lots:

 User user = new User(); // Using the same one over and over, won't work List customers = fetchCustomersFromSomeService(); for(Customer customer : customers) { // User user = new User(); <-- This would work, you get a new one each time user.setId(customer.getId()); user.setName(customer.getName()); saveUserToDB(user); } 

Je faisais également face à ce problème.

La table cible est une table de relations, connectant deux identifiants de différentes tables. J’ai une contrainte UNIQUE sur la combinaison de valeurs, remplaçant le PK. Lors de la mise à jour de l’une des valeurs d’un tuple, cette erreur s’est produite.

Voici à quoi ressemble la table (MySQL):

 CREATE TABLE my_relation_table ( mrt_left_id BIGINT NOT NULL, mrt_right_id BIGINT NOT NULL, UNIQUE KEY uix_my_relation_table (mrt_left_id, mrt_right_id), FOREIGN KEY (mrt_left_id) REFERENCES left_table(lef_id), FOREIGN KEY (mrt_right_id) REFERENCES right_table(rig_id) ); 

La classe Entity pour l’entité RelationWithUnique ressemble essentiellement à ceci:

 @Entity @IdClass(RelationWithUnique.class) @Table(name = "my_relation_table") public class RelationWithUnique implements Serializable { ... @Id @ManyToOne @JoinColumn(name = "mrt_left_id", referencedColumnName = "left_table.lef_id") private LeftTableEntity leftId; @Id @ManyToOne @JoinColumn(name = "mrt_right_id", referencedColumnName = "right_table.rig_id") private RightTableEntity rightId; ... 

Je l’ai réparé par

 // usually, we need to detach the object as we are updating the PK // (rightId being part of the UNIQUE constraint) => PK // but this would produce a duplicate entry, // therefore, we simply delete the old tuple and add the new one final RelationWithUnique newRelation = new RelationWithUnique(); newRelation.setLeftId(oldRelation.getLeftId()); newRelation.setRightId(rightId); // here, the value is updated actually entityManager.remove(oldRelation); entityManager.persist(newRelation); 

Merci beaucoup pour le soupçon de PK, je viens juste de le rater.

Le problème peut également se situer dans différents types de PK de l’object (“User” dans votre cas) et tapez que vous demandez à hibernate pour obtenir session.get(type, id); .

Dans mon cas, l’erreur était l’ identifier of an instance of was altered from 16 to 32 . Le type de PK object était Integer , hibernate a été demandé pour le type Long .