“Entidad separada pasada al error persistir” con el código JPA / EJB

Estoy tratando de ejecutar este código JPA / EJB básico:

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

Me sale este error:

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

¿Algunas ideas?

Busco en internet y la razón que encontré fue:

Esto fue causado por la forma en que creó los objetos, es decir, si establece la propiedad de ID explícitamente. Eliminar la asignación de ID lo solucionó.

Pero no lo obtuve, ¿qué tendré que modificar para que el código funcione?

ERD

Digamos que tiene dos entidades, Album y Photo . El álbum contiene muchas fotos, por lo que es una relación de uno a muchos.

Clase de álbum

 @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 photos = new HashSet(); } 

Clase de fotografía

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

Lo que debe hacer antes de persistir o fusionar es establecer la referencia del álbum en cada fotografía.

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

Así es como adjuntar la entidad relacionada antes de persistir o fusionarse.

El error ocurre porque la identificación del objeto está configurada. Hibernate distingue entre objetos transitorios y separados y persist funciona solo con objetos transitorios. Si la persist concluye que el objeto está separado (lo cual ocurrirá porque la ID está configurada), devolverá el error “objeto separado pasado para persistir”. Puede encontrar más detalles aquí y aquí .

Sin embargo, esto solo se aplica si ha especificado la clave primaria que se generará automáticamente: si el campo está configurado para configurarse siempre manualmente, su código funciona.

retirar

 user.setId(1); 

porque se genera automáticamente en la base de datos y continúa con el comando persistir.

Obtuve la respuesta, estaba usando:

 em.persist(user); 

Usé la fusión en lugar de persistir:

 em.merge(user); 

Pero ni idea, por qué persistir no funcionó. 🙁

si usa para generar la estrategia id = GenerationType.AUTO en su entidad.

Reemplaza user.setId (1) por user.setId (null) , y el problema está resuelto.

Sé que es demasiado tarde y prolijo, todos obtuvieron la respuesta. Pero un poco más para agregar a esto: cuando se establece GenerateType, se espera que persistir () en un objeto genere una identificación.

Si el usuario ya tiene un valor establecido para el Id, hibernate lo trata como un registro guardado, por lo que se trata como separado.

si el ID es nulo, en esta situación se genera una excepción de puntero nulo cuando el tipo es AUTO o IDENTIDAD, etc., a menos que el ID se genere a partir de una tabla, una secuencia, etc.

diseño: esto sucede cuando la tabla tiene una propiedad de frijol como clave principal. GenerateType debe establecerse solo cuando una identificación se genera automáticamente. elimine esto y la inserción debería funcionar con la identificación especificada por el usuario. (es un mal diseño tener una propiedad asignada al campo de clave principal)

Aquí .persist () solo insertará el registro. Si usamos .merge () , se comprobará si existe algún registro con el ID actual. Si existe, se actualizará o, de lo contrario, insertará un nuevo registro.

Tuve este problema y fue causado por el segundo nivel de caché:

  1. Persistí una entidad que usa Hibernate
  2. Luego borré la fila creada de un proceso separado que no interactuó con el segundo nivel de caché
  3. Persistí a otra entidad con el mismo identificador (mis valores de identificador no se generan automáticamente)

Por lo tanto, debido a que el caché no fue invalidado, hibernación asumió que se trataba de una instancia separada de la misma entidad.

Si configura el id en su base de datos para que sea la clave principal y el autoincremento, entonces esta línea de código es incorrecta:

 user.setId(1); 

Prueba con esto:

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

Otro motivo de error es que su objeto entidad no implementa la interfaz 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 { // ... }