SimpleJdbcCall - 执行 oracle 程序时出错

Posted

技术标签:

【中文标题】SimpleJdbcCall - 执行 oracle 程序时出错【英文标题】:SimpleJdbcCall - Error in executing oracle procedure 【发布时间】:2016-06-17 19:37:07 【问题描述】:

我正在尝试从SimpleJdbcCall's execute() 方法(即executing stored procedure in Spring)执行过程,但由于我的包名中有双引号 - "_test_package",它给出了错误。错误说,即使程序确实存在,也要声明它。

我在 Oracle 中有以下程序包 -


Package Spec :-
CREATE OR REPLACE package GOVINDS."_test_package" is

    procedure createHelloMessage(namemsg in out VARCHAR2);

end "_test_package";

Package Body :-
CREATE OR REPLACE package body GOVINDS."_test_package" is

    procedure createHelloMessage(namemsg in out VARCHAR2) is
    begin
        namemsg := 'Hello '|| namemsg;
    end createHelloMessage;

end "_test_package";

我正在尝试从 Spring 的 SimpleJdbcCall 中执行它,如下所示,但它给出了错误,因为 PLS-00201: identifier 'GOVINDS._TEST_PACKAGE' must be declared。

SimpleJdbcCall simpleJdbcCallObject =
    new SimpleJdbcCall(jdbcTemplate).withSchemaName("GOVINDS").withCatalogName("\"_test_package\"").withProcedureName("createHelloMessage")
        .withoutProcedureColumnMetaDataAccess()
        .withNamedBinding()
        .declareParameters(new SqlParameter("namemsg", OracleTypes.VARCHAR));

SqlParameterSource in = new MapSqlParameterSource().addValue("namemsg", "Jim", OracleTypes.VARCHAR);

Map<String, Object> out = simpleJdbcCallObject.execute(in);

错误堆栈跟踪:

org.springframework.jdbc.BadSqlGrammarException: CallableStatementCallback; bad SQL grammar [call GOVINDS."_TEST_PACKAGE".CREATEHELLOMESSAGE(namemsg => ?)]; nested exception is java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00201: identifier 'GOVINDS._TEST_PACKAGE' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:231) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1094) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1130) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jdbc.core.simple.AbstractJdbcCall.executeCallInternal(AbstractJdbcCall.java:405) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jdbc.core.simple.AbstractJdbcCall.doExecute(AbstractJdbcCall.java:365) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.jdbc.core.simple.SimpleJdbcCall.execute(SimpleJdbcCall.java:198) ~[spring-jdbc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
...
...
Caused by: java.sql.SQLException: ORA-06550: line 1, column 7:
PLS-00201: identifier 'GOVINDS._TEST_PACKAGE' must be declared
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:445) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:879) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:450) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:192) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4CCallableStatement.doOall8(T4CCallableStatement.java:204) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.T4CCallableStatement.executeForRows(T4CCallableStatement.java:1041) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]
at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1329) ~[ojdbc6-11.2.0.3.jar:11.2.0.3.0]

如果我尝试使用jdbcTemplate.call() 执行,它工作正常。我更喜欢 SimpleJdbcCall.execute(),因为为了保持一致性,我不想更改 95-97% 的代码。

【问题讨论】:

【参考方案1】:

这是因为,双引号字符串区分大小写,一些 spring JDBC 如何将您的字符串转换为大写,但是您的实际过程名称是小写的。尝试将程序名称更改为大写,您的代码应该可以运行。

【讨论】:

【参考方案2】:

问题是spring jdbc将调用语句字符串转换为大写(甚至对象名称用双引号提供),如果双引号提供的包名区分大小写。

解决方案可以为包名创建同义词。

create or replace synonym GOVINDS.test_package for GOVINDS."_test_package";

【讨论】:

以上是关于SimpleJdbcCall - 执行 oracle 程序时出错的主要内容,如果未能解决你的问题,请参考以下文章

使用simplejdbccall时如何在spring中关闭refcursor

SimpleJdbcCall 不适用于存储的函数

如何使用 simpleJdbcCall 在存储过程中获取 XML 输出参数

如何在 spring 中使用 SimpleJDBCCall 获取存储过程的结果以及两个结果表?

避免多次创建 SimpleJdbcCall

SimpleJdbcCall 忽略 JdbcTemplate 获取大小