ExecuteStoredProcedure 抛出错误代码 17004
ExecuteStoredProcedure throws error code 17004
我正在使用这些库
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
和这个class
CallableStatementCreatorFactory
详细异常
Root Cause: [org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{? = call xxxxxxxxxxxx()}]; SQL state [99999]; error code [17004]; Invalid coloumn: 16; nested exception is java.sql.SQLException: Invalid coloumn: 16]</faultstring>
Map<String, Object> result = QueryExecutor.getInstance().executeStoredProcedure("XXX", null);
不明白我们收到此错误的主要原因?
检查数据类型之间是否不匹配,并确保没有空值或约束。
您的函数 returns 出现了 BOOLEAN
值。 Oracle JDBC driver does not support BOOLEAN
values.
以下 class 重现了类似的错误:
import java.sql.*;
import oracle.jdbc.OracleTypes;
public class Error17004Test {
public static void main(String[] args) throws Exception {
try (Connection c = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:XE", "user", "password")) {
try (Statement stmt = c.createStatement()) {
stmt.execute(
"CREATE OR REPLACE FUNCTION bool_test RETURN BOOLEAN " +
"AS BEGIN RETURN TRUE; END;");
}
try (CallableStatement cstmt = c.prepareCall("{ ? = call bool_test }")) {
cstmt.registerOutParameter(1, OracleTypes.BOOLEAN);
cstmt.execute();
System.out.println("Got result of " + cstmt.getObject(1));
}
}
catch (SQLException e) {
System.out.println("Got a SQLException with message '" + e.getMessage() +
"' and error code " + e.getErrorCode());
}
}
}
当我 运行 时,我得到以下输出:
Got a SQLException with message 'Invalid column type: 16' and error code 17004
幸运的是,有一个简单的解决方法:将您的函数包装在对 sys.diutil.bool_to_int
的调用中。 sys.diutil.bool_to_int
将 BOOLEAN
值 TRUE
、FALSE
和 NULL
分别转换为 1
、0
和 NULL
。然后你只需要从存储过程调用中读取一个整数值而不是布尔值。当然,您随后必须在返回的整数值和您可能想要的布尔值之间进行转换,但这应该很简单。
如果我把上面的class替换成两行
try (CallableStatement cstmt = c.prepareCall("{ ? = call bool_test }")) {
cstmt.registerOutParameter(1, OracleTypes.BOOLEAN);
和
try (CallableStatement cstmt = c.prepareCall(
"{ ? = call sys.diutil.bool_to_int(bool_test) }")) {
cstmt.registerOutParameter(1, Types.INTEGER);
和 运行 我的 class 又一次,我得到以下输出:
Got result of 1
相反。
我正在使用这些库
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
和这个class
CallableStatementCreatorFactory
详细异常
Root Cause: [org.springframework.jdbc.UncategorizedSQLException: CallableStatementCallback; uncategorized SQLException for SQL [{? = call xxxxxxxxxxxx()}]; SQL state [99999]; error code [17004]; Invalid coloumn: 16; nested exception is java.sql.SQLException: Invalid coloumn: 16]</faultstring>
Map<String, Object> result = QueryExecutor.getInstance().executeStoredProcedure("XXX", null);
不明白我们收到此错误的主要原因?
检查数据类型之间是否不匹配,并确保没有空值或约束。
您的函数 returns 出现了 BOOLEAN
值。 Oracle JDBC driver does not support BOOLEAN
values.
以下 class 重现了类似的错误:
import java.sql.*;
import oracle.jdbc.OracleTypes;
public class Error17004Test {
public static void main(String[] args) throws Exception {
try (Connection c = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:XE", "user", "password")) {
try (Statement stmt = c.createStatement()) {
stmt.execute(
"CREATE OR REPLACE FUNCTION bool_test RETURN BOOLEAN " +
"AS BEGIN RETURN TRUE; END;");
}
try (CallableStatement cstmt = c.prepareCall("{ ? = call bool_test }")) {
cstmt.registerOutParameter(1, OracleTypes.BOOLEAN);
cstmt.execute();
System.out.println("Got result of " + cstmt.getObject(1));
}
}
catch (SQLException e) {
System.out.println("Got a SQLException with message '" + e.getMessage() +
"' and error code " + e.getErrorCode());
}
}
}
当我 运行 时,我得到以下输出:
Got a SQLException with message 'Invalid column type: 16' and error code 17004
幸运的是,有一个简单的解决方法:将您的函数包装在对 sys.diutil.bool_to_int
的调用中。 sys.diutil.bool_to_int
将 BOOLEAN
值 TRUE
、FALSE
和 NULL
分别转换为 1
、0
和 NULL
。然后你只需要从存储过程调用中读取一个整数值而不是布尔值。当然,您随后必须在返回的整数值和您可能想要的布尔值之间进行转换,但这应该很简单。
如果我把上面的class替换成两行
try (CallableStatement cstmt = c.prepareCall("{ ? = call bool_test }")) {
cstmt.registerOutParameter(1, OracleTypes.BOOLEAN);
和
try (CallableStatement cstmt = c.prepareCall(
"{ ? = call sys.diutil.bool_to_int(bool_test) }")) {
cstmt.registerOutParameter(1, Types.INTEGER);
和 运行 我的 class 又一次,我得到以下输出:
Got result of 1
相反。