# JPA: Cannot persist detached Objekt



## nero32 (22. Apr 2007)

Hallo Forum,
hab ein Problem mit meinem Java-Programm, hoffe jemand kann mir helfen.
Um es vereinfacht darzustellen, ich habe 2 Entity-Klassen: Bestellung und Bestelldetails, also eine typische OneToMany-Beziehung. 
Die Klasse Bestellung enthält eine Collection bestelldetails. Wenn ich zu einer Bestellung neue Positionen hinzufüge, und die Bestellung mit persist speichern will, bekomme ich folgende Exception:

```
Exception in thread "main" javax.persistence.EntityExistsException: 
Exception Description: Cannot persist detached object [shopsync.db.Bestelldetails[id=0]].
Class> shopsync.db.Bestelldetails Primary Key> [0]
```

Habe inzwischen rausgefunden warum. Als Datenbank benutze ich die MaxDB, die ID's in der Tabelle in der Tabelle Bestelldetails sind sogenannte Autowert-Spalten (bei der MaxDB Typ: int, default serial(1)). Wenn eine neue Zeile in die Tabelle Bestelldetails eingefügt wird, versucht Toplink ein 'NULL' in die Spalte ID einzufügen, was bei der MaxDB nicht zulässig ist, also setze ich das Attribut ID, wenn ich ein neues Bestelldetails-Objekt erzeuge auf 0, damit klappt das Einfügen in die Datenbank und es wird automatisch eine neue ID vergeben. Das Problem ist nun aber, wenn ich mehr als ein Bestelldetails-Objekt in die Bestelldetails-Collection der Klasse Bestellung einfüge und alle eine 0 als ID haben, dann schlägt das "persist" natürlich fehl, Toplink denkt wohl, dass es sich jedesmal um ein und dasselbe Objekt handelt. 
Wie kann ich das umgehen ? Hab schon versucht das Attribut ID auf insertable=false zu setzen, aber bei @Id-Attributen scheint das nicht zu funktionieren.
Ich hoffe, es ist einigermassen verständlich was ich hier geschrieben habe, für Hilfe wäre ich sehr dankbar.

Gruß
Tiberius


----------



## Guest (22. Apr 2007)

Mit Toplink habe ich noch nie gearbeitet, aber vielleicht hilft dir das hier
http://www.oracle.com/technology/products/ias/toplink/jpa/howto/id-generation.html


----------



## Guest (22. Apr 2007)

Versuche zuerst das
	
	
	
	





```
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE)
```
In MySQL4Platform (http://www.oracle.com/technology/pr...entials/platform/database/MySQL4Platform.html)
gibt es die Methode "buildSelectQueryForNativeSequence()", die wie folgt definiert ist

```
public ValueReadQuery buildSelectQueryForNativeSequence()
{
   ValueReadQuery selectQuery = new ValueReadQuery();
   StringWriter writer = new StringWriter();
   writer.write("SELECT LAST_INSERT_ID()");
   selectQuery.setSQLString(writer.toString());
   return selectQuery;
}
```
Dies scheint genau das zu tun, was bei MySQL nötig ist. GenerationType.SEQUENCE sollte also die Lösung sein.


----------



## Guest (22. Apr 2007)

danke für die Antworten. Mir ist gerade folgende Meldung von Toplink aufgefallen: 


> Not able to detect platform for vendor name [SAP DB]. Defaulting to [oracle.toplink.essentials.platform.database.DatabasePlatform]. The database dialect used may not match with the database you are using. Please explicitly provide a platform using property toplink.platform.class.name.



Wenn ich diese Funktion, die du vorschlägst, an MaxDB anpassen und implementieren wollte, müsste ich wohl von  oracle.toplink.essentials.platform.database.DatabasePlatform ableiten und die Funktion buildSelectQueryForNativeSequence() überschreiben, richtig ?
Mein Workaround bisher war folgende Funktion in den betroffenen Entity-Klassen:

```
@PrePersist
    public void test() {
        if(id==null) id=0;
    }
```
Das funktioniert, allerdings muss man das Objekt "refreshen", wenn man die erzeugte ID braucht.


----------



## Guest (22. Apr 2007)

Wie ich schon schrieb, mit Toplink habe ich noch nicht gearbeitet, aber wenn ich es mir
so anschaue, dann wird MaxDB bzw. SAPDB (MaxDB ist ja SAPDB) nicht unterstützt.
Im Package oracle.toplink.essentials.platform.database gibt es kein SAPDBPlatform oder
MaxDBPlatform.
Vielleicht hat bereits jemand diese gemacht und eine funktionierende/getestete Version 
ins Netz gestellt. Such mal danach. Allein das ganze zu schreiben dürfte 'ne Weile dauern. 
Die Methode "buildSelectQueryForNativeSequence()" ist nicht das einzige, was überschrieben
werden müsste. Falls du es doch machst, hol dir am besten den Code von Hibernate und 
schau dir die Defaults zu SAPDB in den *Dialect Klassen an.


----------

