2010-07-16 2 views
6

Diese SQL-Anweisung funktioniert, wenn ich es von meinem Oracle-Client (SQL Developer) laufen:ID Schritte nach INSERT eingefügt ... SELECT auf Oracle

insert into Person (Name) select 'Bob' from dual 

Es funktioniert auch, wenn ich es über Frühling JDBC ausgeben, ohne unter Verwendung eines KeyHolder:

final PreparedStatementCreator psc = new PreparedStatementCreator() { 

    @Override 
    public PreparedStatement createPreparedStatement(Connection con) 
     throws SQLException 
    { 
     return con.prepareStatement(
       "insert into Person (Name) select 'Bob' from dual"); 
    } 
}; 
jdbcOperations.update(psc); 

aber ich brauche eine KEYHOLDER zu verwenden, um die ID der neu eingefügten Zeile zu erhalten. Wenn ich den obigen Code ändern, um eine KEYHOLDER wie folgt zu verwenden:

final KeyHolder keyHolder = new GeneratedKeyHolder(); 
final PreparedStatementCreator psc = new PreparedStatementCreator() { 

    @Override 
    public PreparedStatement createPreparedStatement(Connection con) 
     throws SQLException 
    { 
     return con.prepareStatement(
      "insert into Person (Name) select 'Bob' from dual", 
      new String[] {"PersonID"}); 
    } 
}; 
jdbcOperations.update(psc, keyHolder); 

... dann bekomme ich diesen Fehler:

Exception in thread "main" org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar []; nested exception is java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended 
    at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:94) 
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) 
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:602) 
    at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:842) 
    at au.com.bisinfo.codecombo.logic.ImportServiceImpl.insertLoginRedirectRule(ImportServiceImpl.java:107) 
    at au.com.bisinfo.codecombo.logic.ImportServiceImpl.runImport(ImportServiceImpl.java:68) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) 
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) 
    at $Proxy8.runImport(Unknown Source) 
    at au.com.bisinfo.codecombo.ui.Main.main(Main.java:39) 
Caused by: java.sql.SQLSyntaxErrorException: ORA-00933: SQL command not properly ended 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439) 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395) 
    at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802) 
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436) 
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186) 
    at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521) 
    at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205) 
    at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1008) 
    at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307) 
    at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449) 
    at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3530) 
    at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1350) 
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 
    at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105) 
    at org.springframework.jdbc.core.JdbcTemplate$3.doInPreparedStatement(JdbcTemplate.java:844) 
    at org.springframework.jdbc.core.JdbcTemplate$3.doInPreparedStatement(JdbcTemplate.java:1) 
    at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:586) 
    ... 15 more 

FWIW, alles ist in Ordnung, wenn ich eine INSERT tun ... VALUES statt einer INSERT ... SELECT (obwohl dies mir nicht hilft, wie ich die Dinge auswählen müssen):

final KeyHolder keyHolder = new GeneratedKeyHolder(); 
final PreparedStatementCreator psc = new PreparedStatementCreator() { 

    @Override 
    public PreparedStatement createPreparedStatement(Connection con) 
     throws SQLException 
    { 
     return con.prepareStatement(
      "insert into Person (Name) values ('Bob')", 
      new String[] {"PersonID"}); 
    } 
}; 
jdbcOperations.update(psc, keyHolder); 

ich verwende:

  • Frühling JDBC 3.0.3.RELEASE
  • JDBC-Treiber: ojdbc6.jar Version 11.2.0.1.0
  • RDBMS: Oracle9i Veröffentlichung 9.2.0.5.0 - Produktion
  • commons-dbcp 1,4

NB Meine App muss Standard-SQL verwenden, um db-neutral zu bleiben, was jegliche Oracle-spezifische SQL ausschließt (ich werde nicht aus "Dual" im wirklichen Leben auswählen).

Danke für jede Hilfe.

Antwort

1

java.sql.Connection.prepareStatement(java.lang.String, int) Schnittstelle ist

Creates a default PreparedStatement object that has the capability to retrieve auto-generated keys

Sie verwenden die falsche Methode so klar. Versuchen

return con.prepareStatement(
     "insert into Person (Name) select 'Bob' from dual", 
     Statement.RETURN_GENERATED_KEYS); 

statt

+0

Diese Methode unterstützt wird, ist eines von drei, dass die erzeugten Schlüssel zurückgeben kann, die andere zwei sind prepareStatement (String, int []) und prepareStatement (String, String []). Ich benutze letztere, die IME ist die richtige für Oracle. Trotzdem werde ich deinen Vorschlag versuchen und dich wissen lassen, wie es geht. –

+0

@Andrew Swan Sie haben Recht. Vielen Dank! Aber lass es mich wissen Die Ausgabe –

0

Wie wäre es

INSERT INTO blah b (blah1, blah2, blah3) 
VALUES (?, ?, ?) RETURNING b.id INTO ?"; 
+0

Ich kann nicht INSERT ... VALUES verwenden, weil ich Sachen auswählen muss. Auch möchte ich RETURNING .. INTO nicht verwenden, weil AFAIK es Oracle-spezifisch ist. –

1

Diese Funktion ist nicht von Oracle JDBC-Treiber

+1

Das ist, was ich vermute; Hast du eine Referenz dafür? –

Verwandte Themen