SimpleJdbcCall 不适用于存储的函数

Posted

技术标签:

【中文标题】SimpleJdbcCall 不适用于存储的函数【英文标题】:SimpleJdbcCall doesn't work for a stored function 【发布时间】:2016-12-14 12:23:17 【问题描述】:

我正在尝试通过 Java 在 DB2 上执行存储函数。调用它的函数和代码与 Spring 文档的示例 https://docs.spring.io/spring/docs/current/spring-framework-reference/html/jdbc.html#jdbc-simple-jdbc-call-3 中的非常相似。这是函数声明:

CREATE FUNCTION ST_CLIENT_SEGMENT( p_oib VARCHAR(11) )
    RETURNS VARCHAR(10)
    NO EXTERNAL ACTION

代码如下:

//version1
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate)
    .withSchemaName("VLIB").
    .withFunctionName("ST_CLIENT_SEGMENT")
SqlParameterSource in = new MapSqlParameterSource().addValue("p_oib", "123");
return simpleJdbcCall.executeFunction(String.class, in);

//version2
SimpleJdbcCall simpleJdbcCall = new SimpleJdbcCall(jdbcTemplate)
    .withSchemaName("VLIB")
    .withFunctionName("ST_CLIENT_SEGMENT");
simpleJdbcCall.declareParameters(new SqlParameter("p_oib", Types.VARCHAR));
return simpleJdbcCall.executeFunction(String.class, "123");

//the same exception
//Caused by: java.sql.SQLException: [SQL0440] Routine ST_CLIENT_SEGMENT in VLIB not found with specified parameters.

有人知道为什么会这样吗?当我从我的 SQL 客户端调用该函数时,一切正常。

【问题讨论】:

很多数据库不允许单独调用函数(因为它们只是存储过程),您可以尝试使用函数,例如在选择查询中。 @MarkRotteveel 正如我所说,它适用于我的 SQL 客户端(同一用户)。 “值 vlib.st_client_segment('123');”或“从 SYSIBM.SYSDUMMY1 中选择 VLIB.ST_CLIENT_SEGMENT('123');” 您假设这等效于 SimpleJdbcCall 构造的内容。很可能不是(看代码,其实是在构造一个JDBC转义:? = call vlib.st_client_segment(?),然后需要JDBC驱动翻译。很可能是DB2 JDBC驱动只支持执行存储过程使用 JDBC 调用转义,因此它可能会生成对调用函数无效的 SQL。 【参考方案1】:

我的一位同事找到了解决方案。看来这是一个 DB2 问题http://www.itjungle.com/fhg/fhg102506-story01.html。 我尝试了另一个 SQL,它也给了我一个异常

jdbcTemplate.queryForObject("values vlib.ST_CLIENT_SEGMENT(?)", new Object[] oib, String.class);
//Caused by: java.sql.SQLException: [SQL0418] Use of parameter marker not valid.

修改后一切正常

jdbcTemplate.queryForObject("values vlib.ST_CLIENT_SEGMENT( CAST( ? as CHAR) )", new Object[] oib, String.class);

【讨论】:

以上是关于SimpleJdbcCall 不适用于存储的函数的主要内容,如果未能解决你的问题,请参考以下文章

SimpleJdbcCall 找不到存储过程

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

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

SimpleJdbcCall 忽略 JdbcTemplate 获取大小

SimpleJDBCCall 类参数传递

C++中的函数重载。不适用于 float,适用于 double [重复]