«Entité détachée transmise pour erreur persistante» avec code JPA / EJB

J’essaie d’exécuter ce code de base JPA / EJB:

public static void main(Ssortingng[] args){ UserBean user = new UserBean(); user.setId(1); user.setUserName("name1"); user.setPassword("passwd1"); em.persist(user); } 

Je reçois cette erreur:

 javax.ejb.EJBException: javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: com.JPA.Database 

Des idées?

Je recherche sur Internet et la raison pour laquelle j’ai trouvé était:

Cela a été causé par la façon dont vous avez créé les objects, c’est-à-dire si vous définissez explicitement la propriété ID. Suppression de l’affectation d’ID corrigée.

Mais je ne l’ai pas compris, que devrai-je modifier pour que le code fonctionne?

ERD

Disons que vous avez deux entités Album et Photo . L’album contient beaucoup de photos, donc c’est une relation un à plusieurs.

Classe d’album

 @Entity public class Album { @Id @GeneratedValue(strategy=GenerationType.AUTO) Integer albumId; Ssortingng albumName; @OneToMany(targetEntity=Photo.class,mappedBy="album",cascade={CascadeType.ALL},orphanRemoval=true) Set photos = new HashSet(); } 

Cours de photo

 @Entity public class Photo{ @Id @GeneratedValue(strategy=GenerationType.AUTO) Integer photo_id; Ssortingng photoName; @ManyToOne(targetEntity=Album.class) @JoinColumn(name="album_id") Album album; } 

Ce que vous devez faire avant de continuer ou de fusionner est de définir la référence de l’album dans chaque photo.

  Album myAlbum = new Album(); Photo photo1 = new Photo(); Photo photo2 = new Photo(); photo1.setAlbum(myAlbum); photo2.setAlbum(myAlbum); 

C’est comment attacher l’entité associée avant de persister ou de fusionner.

L’erreur se produit car l’ID de l’object est défini. Hibernate distingue les objects transitoires et détachés et persist uniquement avec les objects transitoires. Si persist conclut que l’object est détaché (ce qui sera le cas parce que l’ID est défini), il retournera l’erreur “object détaché passé pour persister”. Vous pouvez trouver plus de détails ici et ici .

Cependant, cela ne s’applique que si vous avez spécifié la clé primaire à générer automatiquement: si le champ est configuré pour toujours être défini manuellement, votre code fonctionne.

retirer

 user.setId(1); 

car il est généré automatiquement sur la firebase database et continue avec la commande persist.

J’ai eu la réponse, j’utilisais:

 em.persist(user); 

J’ai utilisé la fusion au lieu de persister:

 em.merge(user); 

Mais aucune idée, pourquoi persister n’a pas fonctionné. 🙁

si vous utilisez pour générer la stratégie id = GenerationType.AUTO dans votre entité.

Remplace user.setId (1) par user.setId (null) et le problème est résolu.

Je sais que c’est trop tard et que tout le monde a la réponse. Mais un peu plus à append à cela: lorsque GenerateType est défini, persist () sur un object doit générer un identifiant.

Si l’utilisateur définit déjà une valeur à Id, la mise en veille prolongée le considère comme un enregistrement enregistré et est donc traité comme étant détaché.

si l’identifiant est nul – dans cette situation, une exception de pointeur nul est levée lorsque le type est AUTO ou IDENTITY, etc. sauf si l’ID est généré à partir d’une table ou d’une séquence etc.

design: cela se produit lorsque la table a une propriété bean comme clé primaire. GenerateType doit être défini uniquement lorsqu’un identifiant est généré automatiquement. Supprimez ceci et l’insert devrait fonctionner avec l’ID spécifié par l’utilisateur. (c’est une mauvaise conception d’avoir une propriété mappée sur le champ clé primaire)

Ici, seulement .persist () insérera l’enregistrement. Si nous utilisons .merge (), il vérifiera s’il existe un enregistrement avec l’ID actuel. S’il existe, il sera mis à jour, sinon il insérera un nouvel enregistrement.

J’ai eu ce problème et il a été causé par le cache de second niveau:

  1. J’ai persisté une entité utilisant hibernate
  2. Ensuite, j’ai supprimé la ligne créée à partir d’un processus distinct qui n’interagissait pas avec le cache de second niveau.
  3. J’ai persisté une autre entité avec le même identifiant (mes identifiants ne sont pas générés automatiquement)

Par conséquent, le cache n’étant pas invalidé, hibernate supposait qu’il s’agissait d’une instance détachée de la même entité.

Si vous définissez id dans votre firebase database comme clé primaire et incrémentation automatique, cette ligne de code est incorrecte:

 user.setId(1); 

Essayez avec ceci:

 public static void main(Ssortingng[] args){ UserBean user = new UserBean(); user.setUserName("name1"); user.setPassword("passwd1"); em.persist(user); } 

Une autre raison de l’erreur que votre object entité n’implémente pas l’interface Serializable

 @Entity @Table(name = OddInstance.objectName, uniqueConstraints = @UniqueConstraint(columnNames = {"alias"})) @NamedQueries({ @NamedQuery(name=OddInstance.findByAlias, query="from OddInstance where alias = :alias"), @NamedQuery(name=OddInstance.findAll, query="from OddInstance") }) public class OddInstance implements Serializable { // ... }