Java 使用spring SimpleJDBCall调用Oracle函数
我正在努力与下面的代码,使其工作,搜索文档和论坛和结巴。 最后我决定向你求助。 我拥有的是包含类型、函数声明和函数体声明的包。 将来我想使用MYPACKAGE的同义词(这只是一个模拟-我的数据库中不会有package和types声明,而是使用dblink到外部数据库和Java代码来运行过程/函数,但现在我不允许访问此dblink),MYPACKAGE可以通过dblink访问:Java 使用spring SimpleJDBCall调用Oracle函数,java,oracle,procedure,Java,Oracle,Procedure,我正在努力与下面的代码,使其工作,搜索文档和论坛和结巴。 最后我决定向你求助。 我拥有的是包含类型、函数声明和函数体声明的包。 将来我想使用MYPACKAGE的同义词(这只是一个模拟-我的数据库中不会有package和types声明,而是使用dblink到外部数据库和Java代码来运行过程/函数,但现在我不允许访问此dblink),MYPACKAGE可以通过dblink访问: create public synonym dblink_MYPACKAGE for SOME_SCHEMA.MYPAC
create public synonym dblink_MYPACKAGE for SOME_SCHEMA.MYPACKAGE@dblink_externalDB;
我将在Java代码中使用dblink_MYPACKAGE而不是MYPACKAGE。
(但这没关系吧?)外部数据库不是我们的,所以我们不能在那里更改任何内容
public class TestClassSpringBased {
private DataSource dataSource;
private SimpleJdbcCall jdbcCall;
@Override
public void testMe(Integer id) {
int iid = 1;
SqlParameterSource in = new MapSqlParameterSource().addValue("IN_1", iid);
Map<String, Object> out = jdbcCall.execute(in);
}
public DataSource getDataSource() {
return dataSource;
}
public void setDataSource(DataSource dataSource) {
this.dataSource = dataSource;
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
jdbcTemplate.setResultsMapCaseInsensitive(true);
this.jdbcCall = new SimpleJdbcCall(dataSource)
.withCatalogName("MYPACKAGE")
.withProcedureName("MYFUNCTION")
.withReturnValue()
.useInParameterNames("IN_1")
.declareParameters(
new SqlInOutParameter("IN_1", OracleTypes.NUMBER),
new SqlInOutParameter("OUT_1", OracleTypes.STRUCT, "MYPACKAGE.CUSTOMELEMENTSTYPE",
new SqlReturnType() {
public Object getTypeValue(CallableStatement cs, int colIndx, int sqlType,
String typeName) throws SQLException {
return null; //just let it work, the I will think what to write here
}
}));
}
}
create or replace
PACKAGE MYPACKAGE IS
TYPE CUSTOMELEMENTSTYPE_R IS RECORD (
C1 VARCHAR2(60),
C2 VARCHAR2(30)
);
TYPE CUSTOMELEMENTSTYPE IS TABLE OF CUSTOMELEMENTSTYPE_R
INDEX BY PLS_INTEGER;
FUNCTION MYFUNCTION(
IN_1 IN INTEGER, OUT_1 OUT CUSTOMELEMENTSTYPE )
RETURN VARCHAR2;
END;
create or replace
PACKAGE BODY MYPACKAGE IS
FUNCTION MYFUNCTION(
IN_1 IN INTEGER, OUT_1 OUT CUSTOMELEMENTSTYPE )
RETURN VARCHAR2 IS
BEGIN
SELECT * BULK COLLECT INTO OUT_1
FROM SOME_TABLE;
RETURN 'return param';
END MYFUNCTION;
END MYPACKAGE ;
公共类TestClassSpringBased{
私有数据源;
私有SimpleJdbcCall;
@凌驾
公共void testMe(整数id){
int iid=1;
SqlParameterSource in=new-MapSqlParameterSource().addValue(“in_1”,iid);
Map out=jdbcCall.execute(in);
}
公共数据源getDataSource(){
返回数据源;
}
public void setDataSource(数据源数据源){
this.dataSource=数据源;
JdbcTemplate JdbcTemplate=新的JdbcTemplate(数据源);
setResultsMapCaseSensitive(true);
this.jdbcall=new SimpleJdbcCall(数据源)
.withCatalogName(“MYPACKAGE”)
.withProcedureName(“MYFUNCTION”)
.withReturnValue()
.useInParameterNames(“IN_1”)
.申报参数(
新的SqlInOutParameter(“IN_1”,OracleTypes.NUMBER),
新的SqlInOutParameter(“OUT_1”,OracleTypes.STRUCT,“MYPACKAGE.CUSTOMELEMENTSTYPE”,
新的SqlReturnType(){
公共对象getTypeValue(CallableStatement cs、int-colIndx、int-sqlType、,
字符串类型名)引发SQLException{
returnnull;//让它工作,我会考虑在这里写什么
}
}));
}
}
创建或替换
包我的包是
类型CUSTOMELEMENTSTYPE\u R为记录(
C1瓦查尔2(60),
C2瓦查尔2(30)
);
类型CUSTOMELEMENTSTYPE是CUSTOMELEMENTSTYPE\u R的表
通过PLS_整数进行索引;
函数MYFUNCTION(
IN_1 IN整数,OUT_1 OUT CUSTOMELEMENTSTYPE)
返回VARCHAR2;
结束;
创建或替换
包体我的包是
函数MYFUNCTION(
IN_1 IN整数,OUT_1 OUT CUSTOMELEMENTSTYPE)
返回VARCHAR2是
开始
选择*批量收集到输出1
从某张桌子上;
返回“返回参数”;
结束我的功能;
结束我的包;
错误是:
org.springframework.jdbc.UncategorizedSQLException:CallableStatementCallback;SQL[{=调用MYPACKAGE.MYFUNCTION(?,)}]的未分类SQLException;SQL状态[99999];错误代码[17074];无效的名称模式:MYPACKAGE.CUSTOMELEMENTSTYPE;嵌套异常为java.sql.SQLException:无效的名称模式:MYPACKAGE.CUSTOMELEMENTSTYPE
问题是只有OUT参数,当我不传递参数并对另一个没有OUT参数的MYFUNCTION版本运行它时,相同的代码才能工作
我还尝试了OracleTypes.ARRAY(无效的名称模式)和OracleTypes.OTHER(原因:java.sql.SQLException:错误的列类型:1111)似乎您使用了不正确的方法调用: 您的代码: .withProcedureName(“MYFUNCTION”)[…] 应该由 .withFunctionName[…] 下面是整个函数调用的一些简单示例:
JdbcTemplate jdbc = new JdbcTemplate(txManager.getDataSource());
SimpleJdbcCall jdbcCall = new SimpleJdbcCall(jdbc)
.withCatalogName("p_adm_www")
.withFunctionName("fn_usr_get_login_sequence")
.declareParameters(new SqlOutParameter("RETURN", OracleTypes.NUMBER))
.withoutProcedureColumnMetaDataAccess();
jdbcCall.setAccessCallParameterMetaData(false);
BigDecimal returnId = jdbcCall.executeFunction(BigDecimal.class, null);
return returnId.longValue();
你能解决这个问题吗?就我记忆所及,我们在甲骨文上做过这样的事情。这是jdbc支持的一种类型nod,因此我们在Oracle上编写了一个包装函数/prodecure,调用原始函数,但新函数的参数类型正确。最初的一个是由dblink访问的,因为它不是我们的服务器,我们无法在那里更改任何内容。当然,您可以添加更多的IN或INOUT参数,这同样适用于我,没有任何问题。