Spring JdbcTemplate插入操作抛出未分类的SQLException。

3

我正在使用Spring JDBCTemplate将一行新数据插入到表中。但是jdbcTemplate.update()会抛出以下异常:

PreparedStatementCallback; uncategorized SQLException for SQL []; SQL state [99999]; error code [17090]; operation not allowed

但是,这一行数据已经被插入到了数据库中。

以下是代码:

final StringBuilder widgetInsert = new StringBuilder();
widgetInsert.append("INSERT INTO WIDGET (ID, KEY, DEPT_NUM, TYPE, CREATED_BY_ID, CREATED_DATE) ");
widgetInsert.append("VALUES (WIDGET_SEQ.NEXTVAL, ?, ?, ?, ?, ?) ");

Long widgetId;
try {
    KeyHolder kh = new GeneratedKeyHolder();
    jdbcTemplate.update(
            new PreparedStatementCreator() {
                @Override
                public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
                    PreparedStatement ps = con.prepareStatement(widgetInsert.toString());
                    ps.setLong(1, key);
                    ps.setLong(2, deptNumber);
                    ps.setString(3, widgetType);
                    ps.setLong(4, creatorId);
                    ps.setLong(5, System.currentTimeMillis());
                    return ps;
                }
            }, kh);
    widgetId = kh.getKey().longValue();
} catch (Exception e) {
    // THIS EXCEPTION IS THROWN
    throw new WidgetException("Problem inserting widget for key=" + key, e);
}

编辑:

运行Spring JDBC 3.2.4.RELEASE

完整异常信息如下:

[21] 15/02/02 15:04:59.537 In StandardWrapperValve.invoke(): [127] org.springframework.jdbc.UncategorizedSQLException: PreparedStatementCallback; 未分类的 SQL 异常;SQL []; SQL 状态 [99999]; 错误码 [17090]; 操作不允许;嵌套异常为 java.sql.SQLException: 操作不允许 在 org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:83) 在 org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) 在 org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:80) 在 org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:605) 在 org.springframework.jdbc.core.JdbcTemplate.update(JdbcTemplate.java:849) 在 org.acme.widget.service.WidgetServiceImpl.createWidget(WidgetServiceImpl.java:68) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:606) 在 org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 在 org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) 在 org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) 在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 在 com.sun.proxy.$Proxy21.getOrCreatePersonalOwner(Unknown Source) 在 org.acme.service.BigServiceImpl.addStuff(BigServiceImpl.java:574) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:606) 在 org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) 在 org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:96) 在 org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:260) 在 org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:94) 在 org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) 在 org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204) 在 com.sun.proxy.$Proxy22.addStuff(Unknown Source) 在 org.acme.endpoint.BigRs.addStuff(BigRs.java:262) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 在 java.lang.reflect.Method.invoke(Method.java:606) 在 org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176) 在 org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:440) 在 org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:428) 在 org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:925) 在 org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856) 在 org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936) 在 org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:838) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:646) 在 org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812) 在 javax.servlet.http.HttpServlet.service(HttpServlet.java:727) 在 org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303) 在 org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208) 在 org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52) 在 org.apache.catalina.core.ApplicationFilterChain

你能发布完整的错误信息吗?我使用H2测试没有问题。另外,你的spring-jdbc版本是多少? - chenrui
完整的测试代码在这里 - chenrui
请查看编辑,我无法运行您的代码,因为出现了“无法获取JDBC连接”的错误;嵌套异常是org.h2.jdbc.JdbcSQLException:URL格式错误;必须是“jdbc:h2:{ {。|mem:}[name] | [file:]fileName | {tcp|ssl}:[//]server[:port][,server2[:port]]/name }[;key=value...]”,但实际上是“jdbc:h2:mem:test” [90046-144]。 - Geyser14
如果它对您有效,我想知道问题是否是Oracle特定的,因为我正在使用Oracle运行。 - Geyser14
2个回答

4

在我的代码中,当我使用org.springframework.jdbc.object.BatchSqlUpdate时,我遇到了同样的问题:

BatchSqlUpdate batchSqlUpdate = new BatchSqlUpdate(dataSource, getSqlString(), getSqlTypes(), 1);
KeyHolder keyHolder = new GeneratedKeyHolder();

long result;
int row = batchSqlUpdate.update(getObjParameters(tmpObj), keyHolder);
if (row > 0) 
    result = keyHolder.getKey().longValue();

错误信息如下:

SQL状态[99999];错误代码[17090];操作不允许;嵌套异常是java.sql.SQLException: 操作不允许

在执行更新操作前,我添加了以下两行代码,问题得到了解决:

batchSqlUpdate.setGeneratedKeysColumnNames(new String[]{"id"});
batchSqlUpdate.setReturnGeneratedKeys(true);

3

好的,这个问题已经被解决了。可能是Oracle的要求 - 我不确定,因为我无法在H2上运行chenrui的测试代码。显然,PreparedStatement要求序列化的列必须明确声明。所以对于我的主键列生成序列,我声明如下:

    final String generatedColumns[] = { "ID" };

然后,我将数组传递到PreparedStatementCreator匿名内部类的createPreparedStatement()方法中的prepareStatement()调用中:

    PreparedStatement ps = con.prepareStatement(widgetInsert.toString(), generatedColumns);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接