使用 MyBatis/Spring 执行 Oracle 存储过程并将结果解析为 POJO

execute Oracle stored procedure using MyBatis/Spring and parse results to a POJO

我正在尝试执行 Oracle 存储过程,并将结果映射到 POJO,mybatis/spring 使用注释(即不是 XML)。存储过程的 inputs/outputs 是:

P_INPUT     VARCHAR2         IN                         
P_OUTPUT    VARCHAR2         OUT            
P_COUNT     BINARY_INTEGER   OUT            

POJO 看起来像这样:

public class MyRecord {
    private String output;
    private Integer count;
    // getters and setters...
}

this example 中的代码片段说它适用于 Oracle,对我来说非常适合 MySQL 存储过程。但是,当我尝试对 Oracle 存储过程执行以下操作时:

@Select(value= "{ CALL my_user.some_package.my_proc('${input}') }")
@Options(statementType = StatementType.CALLABLE)
@ResultType(MyRecord.class)
@Results({
                @Result(property="output", column="P_OUTPUT"),
                @Result(property="count", column="P_COUNT"),
         })
MyRecord parseMyInput(@Param("input") String input);

...它引发了以下错误:

bad SQL grammar []; nested exception is java.sql.SQLException: ORA-06550
PLS-00306: wrong number or types of arguments in call to 'my_proc'
PL/SQL: Statement ignored

从错误消息来看,似乎传递给函数的字符串可能与 Oracle 的 VARCHAR2 不兼容,或者我以某种方式发送了多个参数。顺便说一下,我传递给函数的字符串是 (12345).

你能看出我做错了什么吗?

@Jorge 是对的。有必要使用输入参数实例化 POJO:

public class MyRecord {
    private String input;
    private String output;
    private Integer count;
    // getters and setters...
}

然后设置POJO的入参并调用服务:

    MyRecord myRecord = new myRecord();
    myRecord.setInput("myInput");

    dbMapperOracle.parseMyInput(myRecord);

服务调用映射器,传递包含输入(已设置)和输出参数(此时为空)变量的 POJO:

public class DbServiceOracle {

    @Autowired
    @Qualifier("dataSourceOracle")
    private DbMapperOracle dbMapperOracle;

    public MyRecord parseMyInput(MyRecord params){
        dbMapperOracle.parseMyInput(params);
        return params;
    }
}

映射器将从存储过程返回的结果映射到 POJO:

@Select(value= "{ CALL my_user.some_package.my_proc(" +
        "#{input,   mode=IN,  javaType = java.lang.String,  jdbcType=VARCHAR}, " +
        "#{output,  mode=OUT, javaType = java.lang.String,  jdbcType=VARCHAR}, " +
        "#{count,   mode=OUT, javaType = java.lang.Integer, jdbcType=NUMERIC}, "
        ") }")
@Options(statementType = StatementType.CALLABLE)
@ResultType(MyRecord.class)
@Results({
                @Result(property="input", column="P_INPUT"),
                @Result(property="output", column="P_OUTPUT"),
                @Result(property="count", column="P_COUNT"),
        })
MyRecord parseMyInput(MyRecord params);

感谢 Sanjay Kumar,他将 a more complete example 存入了他的 GitHub 帐户。