2010-03-14 3 views
68

Ich versuche, diesen grundlegenden JPA/EJB Code auszuführen:"frei stehende Einheit bestand Fehler bestehen bleiben" mit JPA/EJB Code

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

ich diesen Fehler:

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

Irgendwelche Ideen?

ich im Internet zu suchen und der Grund, warum ich gefunden war:

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

aber ich habe es nicht, was muss ich ändern den Code zum Laufen zu bringen?

Antwort

45

ERD

Nehmen wir an, Sie haben zwei Einheiten Album und Photo. Album enthält viele Fotos, also ist es eine Eins-zu-Viele-Beziehung.

Album Klasse

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

Foto Klasse

@Entity 
public class Photo{ 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    Integer photo_id; 

    String photoName; 

    @ManyToOne(targetEntity=Album.class) 
    @JoinColumn(name="album_id") 
    Album album; 

} 

Was haben Sie zu tun, bevor fortbestehen oder fusionieren ist das Album Referenz in jedem Foto einzustellen.

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

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

So fügen Sie die verknüpfte Entität an, bevor Sie persistieren oder zusammenführen.

+0

Wenn Sie Generics verwenden, müssen Sie nicht "targetEntity = Photo.class" verwenden. – Rollerball

+0

hi, nachdem das Album-Objekt auf photo1 nad photo2 eingestellt wurde ... welches Objekt müssen wir die Liste der Fotos oder des Albums speichern? –

11

bekam ich die Antwort, ich war mit:

em.persist(user); 

Ich benutze merge anstelle von beharren:

em.merge(user); 

Aber keine Ahnung, warum funktioniert hat bestehen nicht. :(

+9

Dies ist nicht die Lösung! –

+0

ich weiß, aber das hat für mich funktioniert. jede andere Antwort hier, die für Sie gearbeitet hat? Wenn ja, dann werde ich mehr als glücklich sein, es auszuwählen. – zengr

+4

Es funktionierte, weil Ihr Objekt von der Hibernationssitzung getrennt wurde oder das Objekt vorübergehend ist, aber Hibernate es als losgelöst sieht, weil Sie den Primärschlüssel deklariert haben. Mit merge fügen Sie das Objekt wieder an die Sitzung an, wodurch Sie Objekte in Ihrem aktualisieren können Datenbank; siehe: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/objectstate.html#objectstate-deached – Ben

112

Der Fehler tritt auf, weil die ID des Objekts festgelegt wird. Hibernate unterscheidet zwischen transienten und frei stehenden Objekten und persist funktioniert nur mit transienten Objekten. Wenn persist das Objekt kommt zu dem Schluss abgelöst wird (was es wird, weil die ID festgelegt ist), es kehrt die „zu frei stehende Objekt übergeben bestehen bleiben“ Fehler Sie und here weitere Details finden

dies gilt jedoch nur wenn Sie den Primärschlüssel angegeben haben, automatisch generiert werden.., wenn das Feld so konfiguriert ist, um immer manuell eingestellt zu werden, funktioniert Ihr Code

+0

Werde ich technisch richtig sein wenn ich sage, ich benutze JPA und nicht Hibernate also, die obige Aussage sollte nicht richtig sein? Ich bin ein Neuling in JPA (3 ays um genau zu sein: P) – zengr

+0

Suns JPA Javadoc (http://java.sun.com/javaee/5/docs/api/javax/persistence/EntityManager.html#persist(java.lang .Object)) und die von Toplink sind genau gleich und legen nahe, dass Sie technisch richtig sind. Allerdings läuft es wirklich darauf hinaus, was die Spezifikation weitergibt() sollte sich verhalten und leider weiß ich nicht, was das ist. –

+0

Diese Lösung hat für mich funktioniert. Ich beharrte auf einem Objekt und behielt die ID irgendwo. Ich möchte dann das vorhandene Objekt mit einem neuen Wert überschreiben, also habe ich das Objekt erstellt, die ID zurückkopiert, und es blies auf, als ich versuchte zu speichern. Am Ende musste ich den DB (findById) erneut anfordern, die Änderungen vornehmen und dann * das * Objekt persistieren. – cs94njw

2

hatte ich dieses Problem und es wurde von der zweiten Ebene Cache verursacht:

  1. ich eine Entität beharrte mit Hibernate
  2. Dann habe ich die Zeile aus einem separaten Prozess erstellt gelöscht, die nicht mit der interagieren haben Cache zweiter Ebene
  3. I eine andere Einheit mit der gleichen Kennung (my Kennungswerte sind nicht automatisch generiert)

daher, weil der Cache nicht ungültig gemacht wurde beibehalten, Hib ernte angenommen, dass es sich um eine losgelöste Instanz derselben Entität handelt.

19

user.setId(1); 

entfernen, weil es automatisch auf dem DB erzeugen ist, und weiterhin mit dem Befehl bestehen.

4

Ich kenne seine Art von zu spät und Prolye jeder bekam die Antwort. Aber etwas mehr hinzuzufügen: Wenn GenerateType gesetzt ist, wird erwartet, dass persist() für ein Objekt eine ID generiert.

Wenn der Benutzer bereits einen Wert für die ID festgelegt hat, behandelt Hibernate ihn als gespeicherten Datensatz und wird daher als getrennt behandelt.

wenn die ID ist null - in dieser Situation eine Null-Zeiger-Ausnahme wird ausgelöst, wenn der Typ AUTO oder IDENTITY usw., es sei denn die ID aus einer Tabelle oder ein sequece usw.

Design erzeugt wird, ist: dies geschieht, wenn die Tabelle hat eine Bean-Eigenschaft als Primärschlüssel. GenerateType muss nur festgelegt werden, wenn eine ID automatisch generiert wird. entfernen Sie dies und der Einsatz sollte mit der benutzerdefinierten ID arbeiten. (Es ist ein schlechtes Design, eine Eigenschaft dem Primärschlüsselfeld zuzuordnen)

4

Hier wird .persist() nur den Datensatz einfügen. Wenn wir .merge() verwenden, wird geprüft, ob dort ein Datensatz mit dem aktuellen existiert ID, wenn es existiert, wird es aktualisiert, andernfalls wird ein neuer Datensatz eingefügt.

+0

Es kostete mich eine Menge Zeit, bis ich deine Antwort bekam. Vielen Dank! –

7

Wenn Sie verwenden, um die id = GenerationType.AUTO Strategie in Ihrer Entität zu generieren.

Ersetzt user.setId (1) von user.setId (null), und das Problem ist gelöst.

1

Wenn Sie ID in Ihrer Datenbank einstellen, Primärschlüssel und autoincrement sein, dann ist diese Zeile Code ist falsch:

user.setId(1); 

mit Try this:

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

Ich habe das versucht und ich weiß, diesen Fehler zu bekommen: 'losgelöstes Wesen bestanden, um fortzufahren' – s1ddok

0

Ein weiterer Grund für Fehler, dass Ihr Entitätsobjekt implementiert Serializable Schnittstelle

@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 { 
    // ... 
} 
Verwandte Themen