2010-03-14 12 views
68

Sto cercando di eseguire questo codice JPA/EJB di base:"entità indipendente passato al persistere di errore" con il codice di JPA/EJB

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

ottengo questo errore:

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

Tutte le idee?

che cerco su internet e il motivo per cui ho trovato è stato:

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

ma non ho capito, che cosa dovrò modificare per ottenere il codice di lavoro?

risposta

45

ERD

Supponiamo di avere due entità Album e Photo. L'album contiene molte foto, quindi è una relazione uno a molti.

classe 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>(); 
} 

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

} 

Quello che devi fare prima di persistere o unire è quello di impostare il riferimento Album in ogni foto.

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

     photo1.setAlbum(myAlbum); 
     photo2.setAlbum(myAlbum);  

Ecco come allegare l'entità correlata prima di persistere o unire.

+0

Se si utilizzano i generici, non è necessario utilizzare "targetEntity = Photo.class" – Rollerball

+0

hi, dopo aver impostato l'oggetto album su foto1 e foto2 ... quale oggetto è necessario salvare l'elenco di foto o album? –

11

ho avuto la risposta, stavo usando:

em.persist(user); 

ho usato unione in luogo di persistere:

em.merge(user); 

Ma nessuna idea, perché persistono non ha funzionato. :(

+9

questa non è la soluzione! –

+0

lo so, ma questo ha funzionato per me. qualche altra risposta qui che ha funzionato per te? se sì, allora sarò più che felice di selezionarlo. – zengr

+4

Ha funzionato perché il tuo oggetto è stato staccato dalla sessione di sospensione o l'oggetto è transitorio ma Hibernate lo vede come distaccato perché hai ottenuto la chiave primaria dichiarata, Con l'unione si collega nuovamente l'oggetto alla sessione questo ti permette di aggiornare gli oggetti nel tuo Banca dati; vedi: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-detached – Ben

112

L'errore si verifica perché l'ID dell'oggetto è impostato. Sospensione distingue tra oggetti transitori e indipendenti e persist funziona solo con oggetti transitori. Se persist conclude l'oggetto viene rimosso (che verrà perché l'ID è impostato), essa restituirà "l'oggetto distaccato passato a persistere" errore è possibile trovare maggiori dettagli e here

Tuttavia, questo vale solo se è stata specificata la chiave primaria per essere generato automaticamente:.. se il campo è configurato per essere sempre impostato manualmente, allora il tuo codice funziona.

+0

Sarò tecnicamente corretto quando dico, sto usando JPA e non Hibernate quindi, quella dichiarazione sopra non dovrebbe applicarsi giusto? Sono newbie in JPA (3 ays per la precisione: P) – zengr

+0

Sun's JPA Javadoc (http://java.sun.com/javaee/5/docs/api/javax/persistence/EntityManager.html#persist(java.lang .Oggetto)) e quello di Toplink sono esattamente gli stessi e suggeriscono di essere tecnicamente giusti. Tuttavia, si riduce davvero a ciò che dice la specifica persist() dovrebbe comportarsi come e purtroppo, non so di cosa si tratta. –

+0

Questa soluzione ha funzionato per me. Stavo persistendo un oggetto, mantenendo l'ID memorizzato da qualche parte. Poi voglio sovrascrivere quell'oggetto esistente con un nuovo valore, quindi ho creato l'oggetto, ho copiato l'ID di nuovo e si è verificato quando ho provato a salvare. Alla fine, ho dovuto interrogare il DB (findById), apportare le modifiche e quindi persistere * quell'oggetto *. – cs94njw

2

Ho avuto questo problema ed è stato causato dalla cache di secondo livello:

  1. insistetti un'entità utilizzando hibernate
  2. Poi ho cancellato la riga creata da un processo separato che non interagiscono con la cache di secondo livello
  3. insistetti un'altra entità con lo stesso identificatore (i miei valori di identificatore non sono generati automaticamente)

Quindi, perché la cache non è stata invalidata, Hib ernate pensava che si trattasse di un'istanza distaccata della stessa entità.

19

rimuovere

user.setId(1); 

perché è automaticamente generare il DB, e continuare con il comando persistere.

4

Conosco il suo tipo di troppo tardi e ogni volta ha la risposta. Ma un po 'di più da aggiungere a questo: quando GenerateType è impostato, persist() su un oggetto è previsto ottenere un ID generato.

Se esiste già un valore impostato per l'ID dall'utente, Hibernate lo considera come record salvato e quindi viene considerato come rimosso.

se l'id è nullo - in questa situazione un'eccezione di puntatore nullo viene generato quando il tipo è AUTO o IDENTITÀ ecc meno che l'id è generato da una tabella o una

disegno sequece ecc: questo avviene quando la la tabella ha una proprietà bean come chiave primaria. GenerateType deve essere impostato solo quando un ID viene generato automaticamente. rimuovere questo e l'inserto dovrebbe funzionare con l'id specificato dall'utente. (è una cattiva progettazione per avere una proprietà mappata al campo chiave primaria)

4

Qui .persist() inserirà solo il record.Se usiamo .merge() controllerà che esiste un record con l'attuale ID, se esiste aggiornerà altrimenti inserirà nuovo record.

+0

Mi è costato un sacco di tempo finché non ho ricevuto la tua risposta. Grazie mille! –

7

se si utilizza per generare la strategia id = GenerationType.AUTO nell'entità.

Sostituisce user.setId (1) di user.setId (null) e il problema è risolto.

1

Se si imposta id nel database per essere chiave primaria e AutoIncrement, allora questa riga di codice è sbagliato:

user.setId(1); 

prova con questo:

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

Ho provato e so di aver ricevuto questo errore: 'Entità distaccata passata a persistere' – s1ddok

0

Un altro motivo per l'errore che il vostro l'oggetto entità non implementa l'interfaccia 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 { 
    // ... 
} 
Problemi correlati