【问题标题】:cannot receive out parameter from oracle procedure executed by mybatis无法从mybatis执行的oracle过程中接收到out参数
【发布时间】:2011-12-10 15:47:31
【问题描述】:

我使用 Spring 3.0.5 开发 java 应用程序,并使用 mybatis-spring 与数据库 Oracle 合作。

我有一个mybatis的接口:

public interface SubscriberMapper {
    Subscriber getSubscriberByMsisdn(String msisdn);

    void insertSubscriber(Subscriber subscriber);

    void updateSubscriber(Subscriber subscriber);

    void canCustomerSubscribe(@Param("msisdn") String msisdn, 
                         @Param("responseCode") Integer responseCode);

}

canCustomerSubscribe 的 mybatis xml 内容:

<parameterMap id="canCustomerSubscribeParams" type="map">
    <parameter property="msisdn" jdbcType="VARCHAR" javaType="java.lang.String" mode="IN"/>
    <parameter property="responseCode" jdbcType="NUMERIC" javaType="java.lang.Integer" mode="OUT"/>
</parameterMap>
<select id="canCustomerSubscribe" parameterMap="canCustomerSubscribeParams" statementType="CALLABLE">
    CALL wallet.pkg_wallet_validation.can_customer_subscribe(#{msisdn}, #{responseCode})
</select>

和要执行的代码:

public void subscribe(String msisdn) throws InvalidArgumentException {
    Integer responseCode = 0;
    subscriberMapper.canCustomerSubscribe(msisdn, responseCode);
    System.out.println("msisdn: " + msisdn + ", responseCode: " + responseCode);
}

当我使用无效的“msisdn”执行“订阅”方法时,我没有从过程中收到真正的输出值。在数据库中执行此过程返回reponseValue = 1001,但在Java代码中我收到0。我为mybatis打开了调试日志记录,输出为:

2011-10-19 10:32:46,732 调试 [main] (Slf4jImpl.java:28) ooo 连接已打开
2011-10-19 10:32:46,909 调试 [main] (Slf4jImpl.java:28) ==> 执行:调用 wallet.pkg_wallet_validation.can_customer_subscribe(?, ?)
2011-10-19 10:32:46,911 调试 [main] (Slf4jImpl.java:28) ==> 参数:509999999(字符串),0(整数)
msisdn:509999999,响应代码:0

当我更改“订阅”方法 responseCode = null 时,我收到并出错:

org.springframework.jdbc.UncategorizedSQLException:设置空参数时出错。大多数 JDBC 驱动程序要求必须为所有可为空的参数指定 JdbcType。原因:java.sql.SQLException:无效的列类型
; SQL [] 的未分类 SQLException; SQL 状态 [null];错误代码 [17004];无效的列类型;嵌套异常是 java.sql.SQLException: Invalid column type

【问题讨论】:

    标签: java oracle spring stored-procedures mybatis


    【解决方案1】:

    我找到了解决方案。 map 必须是用户,而不是 canCustomerSubscribe 方法中的两个参数。

     void canCustomerSubscribe(Map<String,Object> params);
    

    mybatis xml内容:

    <select id="canCustomerSubscribe" parameterType="java.util.HashMap" statementType="CALLABLE">
        CALL wallet.pkg_wallet_validation.can_customer_subscribe(
        #{msisdn, jdbcType=VARCHAR, javaType=java.lang.String, mode=IN},
        #{responseCode,jdbcType=NUMERIC, javaType=java.lang.Integer, mode=OUT})
    </select>
    

    (我需要在参数属性之间添加逗号)

    从订阅服务方法调用它:

    public void subscribe(String msisdn) throws InvalidArgumentException {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("msisdn", msisdn);
        params.put("responseCode", null);
        subscriberMapper.canCustomerSubscribe(params);
        System.out.println(params.get("responseCode"));
    }
    

    【讨论】:

    • 我更正了XML文件的语法,我需要在参数属性之间添加逗号!