在INSERT … SELECT之后获取插入的ID

前端之家收集整理的这篇文章主要介绍了在INSERT … SELECT之后获取插入的ID前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

如果我从Oracle客户端(sql Developer)运行它,则此sql语句有效:

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

如果我通过Spring JDBC发布它,而不使用KeyHolder,它也可以工作:

  1. final PreparedStatementCreator psc = new PreparedStatementCreator() {
  2. @Override
  3. public PreparedStatement createPreparedStatement(Connection con)
  4. throws sqlException
  5. {
  6. return con.prepareStatement(
  7. "insert into Person (Name) select 'Bob' from dual");
  8. }
  9. };
  10. jdbcOperations.update(psc);

但是我需要使用KeyHolder来获取新插入的行的ID.如果我改变上面的代码使用KeyHolder如下:

  1. final KeyHolder keyHolder = new GeneratedKeyHolder();
  2. final PreparedStatementCreator psc = new PreparedStatementCreator() {
  3. @Override
  4. public PreparedStatement createPreparedStatement(Connection con)
  5. throws sqlException
  6. {
  7. return con.prepareStatement(
  8. "insert into Person (Name) select 'Bob' from dual",new String[] {"PersonID"});
  9. }
  10. };
  11. jdbcOperations.update(psc,keyHolder);

…然后我收到此错误

  1. 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
  2. at org.springframework.jdbc.support.sqlExceptionSubclassTranslator.doTranslate(sqlExceptionSubclassTranslator.java:94)
  3. at org.springframework.jdbc.support.AbstractFallbacksqlExceptionTranslator.translate(AbstractFallbacksqlExceptionTranslator.java:72)
  4. at org.springframework.jdbc.support.AbstractFallbacksqlExceptionTranslator.translate(AbstractFallbacksqlExceptionTranslator.java:80)
  5. at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:602)
  6. at org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:842)
  7. at au.com.bisinfo.codecombo.logic.ImportServiceImpl.insertLoginRedirectRule(ImportServiceImpl.java:107)
  8. at au.com.bisinfo.codecombo.logic.ImportServiceImpl.runImport(ImportServiceImpl.java:68)
  9. at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  10. at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
  11. at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
  12. at java.lang.reflect.Method.invoke(Method.java:597)
  13. at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
  14. at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
  15. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
  16. at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
  17. at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
  18. at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
  19. at $Proxy8.runImport(Unknown Source)
  20. at au.com.bisinfo.codecombo.ui.Main.main(Main.java:39)
  21. Caused by: java.sql.sqlSyntaxErrorException: ORA-00933: sql command not properly ended
  22. at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:439)
  23. at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:395)
  24. at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:802)
  25. at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:436)
  26. at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:186)
  27. at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:521)
  28. at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:205)
  29. at oracle.jdbc.driver.T4CPreparedStatement.executeForRows(T4CPreparedStatement.java:1008)
  30. at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1307)
  31. at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3449)
  32. at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate(OraclePreparedStatement.java:3530)
  33. at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeUpdate(OraclePreparedStatementWrapper.java:1350)
  34. at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
  35. at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:105)
  36. at org.springframework.jdbc.core.JdbcTemplate$3.doInPreparedStatement(JdbcTemplate.java:844)
  37. at org.springframework.jdbc.core.JdbcTemplate$3.doInPreparedStatement(JdbcTemplate.java:1)
  38. at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:586)
  39. ... 15 more

FWIW,一切都很好,如果我做一个INSERT … VALUES而不是INSERT … SELECT(虽然这对我没有帮助,因为我需要选择东西):

  1. final KeyHolder keyHolder = new GeneratedKeyHolder();
  2. final PreparedStatementCreator psc = new PreparedStatementCreator() {
  3. @Override
  4. public PreparedStatement createPreparedStatement(Connection con)
  5. throws sqlException
  6. {
  7. return con.prepareStatement(
  8. "insert into Person (Name) values ('Bob')",keyHolder);

我正在使用:

> Spring JDBC 3.0.3.RELEASE
> JDBC驱动程序:ojdbc6.jar版本11.2.0.1.0
> RDBMS:Oracle9i版本9.2.0.5.0 – 生产
> commons-dbcp 1.4

注:我的应用程序需要使用标准sql才能保持数据库中立,这排除了任何特定于Oracle的sql(我不会在现实生活中选择“双重”).

谢谢你的帮助.

最佳答案
java.sql.Connection.prepareStatement(java.lang.String,int)界面清晰

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

所以你使用的是错误方法.尝试

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

代替

猜你在找的Spring相关文章