2010-03-14 18 views
68

Estoy tratando de ejecutar este código básico JPA/EJB:"entidad independiente pasó a persistir error" con el código de JPA/EJB

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

consigo este error:

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

¿Alguna idea?

que busco en Internet y la razón por la que encontré fue:

This was caused by how you created the objects, i.e. If you set the ID property explicitly. Removing ID assignment fixed it.

Pero yo no entiendo, ¿qué voy a tener que modificar para obtener el código de trabajo?

Respuesta

45

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

clase 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; 

} 

Lo que tienes que hacer antes de persistir o fusionar es necesario ajustar la referencia del álbum de fotos cada uno.

 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 fusionar.

+0

Si usa genéricos, no es necesario utilizar "targetEntity = Photo.class" – Rollerball

+0

hola, después de configurar el objeto del álbum en photo1 nad photo2 ... ¿qué objeto tenemos para guardar la lista de Fotos o Álbum? –

11

Tengo la respuesta, yo estaba usando:

em.persist(user); 

que utilizan fusión en lugar de persistir:

em.merge(user); 

Pero ni idea, ¿por qué persisten no funcionó. :(

+9

¡esta no es la solución! –

+0

lo sé, pero esto funcionó para mí. ¿Alguna otra respuesta aquí que funcionó para ti? si es así, entonces estaré más que feliz de seleccionarlo. – zengr

+4

Funcionó porque su objeto se separó de la sesión de hibernación o el objeto es transitorio pero el hibernación lo ve como separado porque se obtuvo la clave primaria declarada. Con usar fusionar, se adjunta el objeto a la sesión nuevamente, esto le permite actualizar objetos en su base de datos; ver: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate -detached – Ben

112

El error se produce porque el ID del objeto se establece. Hibernate distingue entre objetos transitorios y que fueron separados y persist sólo funciona con objetos transitorios. Si persist concluye el objeto se separa (que será debido a que la ID se establece), se devolverá el "objeto distante pasado a persistir" error puede encontrar más detalles y here

Sin embargo, esto sólo se aplica si ha especificado la clave principal para ser auto-generada:.. si se ha configurado el campo para establecerse siempre manualmente, su código funciona.

+0

¿Seré técnicamente correcto cuando digo, estoy usando JPA y no Hibernate entonces, esa declaración anterior no debería aplicarse ¿verdad? Soy novato en JPA (3 a. Para ser precisos: P) – zengr

+0

JPA Javadoc de Sun (http://java.sun.com/javaee/5/docs/api/javax/persistence/EntityManager.html#persist(java.lang) .Object)) y el de Toplink son exactamente iguales y sugieren que técnicamente es correcto. Sin embargo, realmente se reduce a lo que la especificación dice persist() debería comportarse y, lamentablemente, no sé qué es eso. –

+0

Esta solución funcionó para mí. Estaba persistiendo un objeto, manteniendo el ID almacenado en algún lugar. Luego quiero sobrescribir ese objeto existente con un nuevo valor, así que creé el objeto, copié el ID nuevamente, y explotó cuando traté de guardarlo. Al final, tuve que volver a consultar el DB (findById), hacer los cambios, y luego persistir * ese * objeto. – cs94njw

2

he tenido este problema y que fue causado por el caché de segundo nivel:

  1. Persistí una entidad usando Hibernate
  2. Entonces suprime la línea creada a partir de un proceso separado que no interactúan con el caché de segundo nivel
  3. I persistió otra entidad con el mismo identificador (mis valores de identificador no son auto-generado)

Por lo tanto, debido a que el caché no fue invalidado, Hib ernate supuso que se trataba de una instancia separada de la misma entidad.

19

eliminar

user.setId(1); 

porque es automático genera en la base de datos, y continuar con persistir comando.

4

Sé que su tipo de Proly demasiado tarde y cada uno tiene la respuesta. Sin embargo, poco más que añadir a esto: cuando se establece GenerateType, persisten() en un objeto se espera para obtener una ID generado.

Si hay un valor establecido para la identificación por el usuario ya, hibernar lo trata como registro guardado y por lo que se considera como independiente.

si el ID es nulo - en esta situación se planteó una excepción de puntero nulo cuando el tipo es AUTO o identidad, etc a menos que el id se genera a partir de una tabla o una sequece etc. Diseño

: esto ocurre cuando el la tabla tiene una propiedad de frijol como clave principal. GenerateType deben establecerse sólo cuando se genera automáticamente un ID. eliminar esta y el inserto debe trabajar con el especificado por el usuario ID. (es un mal diseño tener una propiedad asignada al campo de clave principal)

4

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

+0

Me costó un montón de tiempo hasta que obtuve tu respuesta. ¡Muchas gracias! –

7

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

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

1

Si establece id en su base de datos a ser clave primaria y autoincrement, a continuación, esta línea de código es incorrecto:

user.setId(1); 

Pruebe con esto:

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

Lo intenté y sé que obtuve este error: 'entidad separada pasó a persistir' – s1ddok

0

Otra razón para el error de que su objeto entidad no implementa Serializable interfaz

@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 { 
    // ... 
} 
Cuestiones relacionadas