J'essaie d'exécuter ce code JPA/EJB de base:
public static void main(String[] 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?
J'ai cherché sur Internet et la raison pour laquelle j'ai trouvé était:
Cela était dû à la manière dont vous avez créé les objets, c’est-à-dire si vous définissez explicitement la propriété ID. La suppression de l'attribution d'identifiant a résolu le problème.
Mais je n'ai pas compris, que vais-je devoir modifier pour que le code fonctionne?
Supposons que vous avez deux entités Album
et Photo
. L'album contient de nombreuses photos, il s'agit donc d'une relation un à plusieurs.
Classe d'album
@Entity
public class Album {
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
Integer albumId;
String albumName;
@OneToMany(targetEntity=Photo.class,mappedBy="album",cascade={CascadeType.ALL},orphanRemoval=true)
Set<Photo> photos = new HashSet<Photo>();
}
Cours de photo
@Entity
public class Photo{
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
Integer photo_id;
String photoName;
@ManyToOne(targetEntity=Album.class)
@JoinColumn(name="album_id")
Album album;
}
Avant de continuer ou de fusionner, vous devez 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 parce que l'ID de l'objet est défini. Hibernate distingue les objets transitoires des objets détachés et persist
fonctionne uniquement avec les objets transitoires. Si persist
conclut que l'objet est détaché (ce qui sera le cas parce que l'ID est défini), l'erreur "erreur de retour de l'objet détaché est renvoyée". Vous pouvez trouver plus de détails ici et ici .
Cependant, ceci 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 auto-généré sur la base de données, et continue avec la commande persist.
J'ai eu la réponse, j'utilisais:
em.persist(user);
J'ai utilisé fusionner à la place de persist:
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 petit peu plus à ajouter à cela: lorsque GenerateType est défini, persist () sur un objet devrait obtenir un identifiant généré.
Si une valeur est déjà définie par l'utilisateur par l'id, hibernate la traite comme un enregistrement sauvegardé et est donc traitée comme détachée.
si l'id est null - dans cette situation, une exception de pointeur null est déclenché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é de bean en tant que clé primaire . GenerateType doit être défini uniquement lorsqu'un identifiant est généré automatiquement . supprimez-le et l'insertion doit fonctionner avec l'ID spécifié par l'utilisateur .. est une mauvaise conception pour avoir une propriété mappée sur le champ de clé primaire)
Ici .persist () seulement insérera l'enregistrement.Si nous utilisons .merge () il va vérifier s'il existe un enregistrement avec l'ID actuel, s'il existe, il se mettra à jour sinon un nouveau disque.
Si vous définissez id dans votre base de données comme clé primaire et auto-incrémentation, cette ligne de code est incorrecte:
user.setId(1);
Essayez avec ceci:
public static void main(String[] args){
UserBean user = new UserBean();
user.setUserName("name1");
user.setPassword("passwd1");
em.persist(user);
}
J'ai eu ce problème et il a été causé par le cache de second niveau:
Ainsi, le cache n’ayant pas été invalidé, hibernate a supposé qu’il s’agissait d’une instance détachée de la même entité.
Une autre raison d'erreur que votre objet d'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 {
// ...
}