Für alle die auch schlau werden wollen - hier mal eine Lösung
Das Problem ist das gleiche wie im benachbarten Thread …
Statement.RETURN_GENERATED_KEYS wird vom Postgres Jdbc Treiber nit unterstuetzt.
Hier eine Lösung - Ein Tip mal nach einer RETURNING Anweisung zu schauen, die man an ein INSERT statment haengen kann brachte schließlich den gewünschten Erfolg.
Und zwar lässt liefert die Methode Statement.execute(String sql) einen boolean, welcher darüber Auskunft gibt, ob hernach ein Resultset zur Verfügung steht. Anders als bei der üblichen Verwendung von Statement.RETURN_GENERATED_KEYS stellt der PG Jdbc-Treiber ein solches ResultSet doch tatsächlich an statement.getResultSet() bereit (statt statement.getGeneratedKeys() == Sackgasse). Nun - Auch gut. Über dieses kann man wunderbar, den (oder die) generierten Keys auslesen - sogar über den Namen der jeweiligen Columns. Es geht sogar noch mehr - dazu komm ich nach dem kleinen Beispiel:
// my convention ..
private static final int UNKNOWN_ID = 0;
.....
String qry = "INSERT INTO foo (bla, blub ... ) "+
" VALUES (bli, blo, ... ) [B]RETURNING [color=RoyalBlue]myPKcolumn[/color][/B][color=RoyalBlue]";[/color]
if (statement.execute(qry)) {
// ResultSet available ..
ResultSet resultSet = [color=Red]statement.getResultSet();[/color]
try {
int pkColumnIndex;
if (resultSet.first() &&
[color=DimGray] // I know - thats not necessary .. but I'm paranoid :) [/color]
(pkColumnIndex = resultSet.findColumn([color=RoyalBlue]"myPKcolumn"[/color])) > 0) {
lastID = resultSet.getInt(pkColumnIndex);
} else {
lastID = UNKNOWN_ID;
}
} finally {
resultSet.close();
}
} else {
// no ResultSet available ..
lastID = UNKNOWN_ID;
}
Alles akzeptabel … keine überflüssigen TX … kein Race-Condition-Problem … auch wenn man ein bissel was PG-Spezifisches coden muss.
In diversen Foren od. Mailinglisten habe ich z.B. gelesen, dass sich die Leute den Kopf darueber zerbrechen welchen Index eine Autowert-PK Column in ihrer Table hat, um dem RETURNING eben diesen Index anzugeben (z.B. … RETURNING 4 … funktioniert ja auch) - denn ein PK kann ja an beliebiger Stelle stehen. (PK’s über mehrere Felder lassen wir erstmal aussen vor)
Dabei koennte man für eine Unterstützung von Statement.RETURN_GENERATED_KEYS doch auch einfach RETURNING * (ja das geht auch - liefert alle Felder - nicht nur jene die im INSERT verwendet wurden) anhaengen, um über die PG-Metadaten (API) im Nachhinein den PK zu finden (mehr oder weniger effizient), je nachdem ob die API ueberhaupt verrät, ob eine Column als “PRIMARY_KEY” deklariert wurde. Zumindest hat man die OID der Column - mit der man sicher weiter kommt.
Wie dem auch sei - selbst das sollte für eine Unterstuetzung von Statement.RETURN_GENERATED_KEYS obsolete sein, da Statement.getGeneratedKeys() keine Vorgaben macht, wie das ResultSet auszuschauen hat. Da wäre es sicherlich auch nicht gänzlich falsch, das gesamte Tupel zu fetchen (wenn man drauf zugreift). Man bekaeme auch gleich noch alle sonstigen erzeugten DEFAULT-Werte und weiss der Geier was generiert würde. Ob die NICHT-generierten Werte in diesem Resultset jemanden wirklich stören - sei dahingestellt - mich würde das entzücken.
Es waren auch Bedenken zu lesen, dass man ja dieses RETURNING auch gern mal selbst Anwendungsbedingt an ein INSERT hängen möchte. Aber auch das ist kein Problem, denn RETURNING myAPPGenKey, mySecondAPPGenKey, * akzeptiert PG ebenso wie RETURNING *, *. Da muss der Jdbc-Treiber noch nichtmal viel denken, und könnte sowohl ein “Custom RETURNING” als auch ein “BuildIn RETURNING” gleichzeitig bedienen.
Viel Spass
Gruß
Steffen
p.s. kann momentan leider nicht auf das PG-CVS zugreifen … sonst wuerde ich mich selbst dran machen einen Patch fuer zu bauen.