通过BeanPropertySqlParameterSource存储枚举属性失败,出现SQLException:请求的转换无效

时间:2015-08-20 22:31:09

标签: spring oracle spring-jdbc

Java,Spring JDBC v3.0.5

我定义了一个DTO,其中包含自定义枚举类型的属性。 当通过 BeanPropertySqlParameterSource 对象将其作为参数发送到存储过程调用时,所有其他属性("普通"类型,如:Long,String和Boolean)工作正常,除了枚举类型。它抛出:

java.sql.SQLException: Invalid conversion requested

查看StatementCreatorUtils.java方法 setValue()我看到它不处理Types.CHAR,它是枚举对象的sqlType(我从调试中知道这一点 - 实际上是SQL过程中声明的参数类型。)

通过 BeanPropertyRowMapper 读取相同的DTO(通过其他程序)可以正常工作。

这是Spring代码中的一些错误或遗漏吗?

DTO看起来像这样:

public class MyDTO extends Serializable {
    private Long num;
    private Boolean bool;
    private String str;

    public static enum MyEnum { A , B }
    private MyEnum en;
    // getters and setters omitted 
}

// the call:
new SimpleJdbcCall(m_dataSource).withProcedureName("procedureName").withSchemaName("schema").executeObject(BigDecimal.class, new BeanPropertySqlParameterSource(aMyDTO)).longValue();

我解决了这个问题,让 MyEnum 实现 java.lang.CharSequence 接口,所以 isStringValue()< StatementCreatorUtils 类中的/ em>方法&#34;认为&#34;它是一个字符串并调用:

ps.setString(paramIndex, inValue.toString());

与上面的几行相同:

    else if (sqlType == Types.VARCHAR || sqlType == Types.LONGVARCHAR ||
            (sqlType == Types.CLOB && isStringValue(inValue.getClass()))) {
        ps.setString(paramIndex, inValue.toString());
    }

被跳过,因为它不允许使用CHAR sqlType。

使用的数据库是Oracle,并且从Oracle驱动程序抛出实际异常,因此它有类似的问题(无法从枚举转换为String)。 过程参数定义为&#34; IN CHAR&#34;。

抛出的异常是:

Caused by: java.sql.SQLException: Invalid conversion requested
at oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:13780)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:13682)
at oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:14515)
at oracle.jdbc.driver.OracleCallableStatement.setObject(OracleCallableStatement.java:10918)
at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:735)
at org.springframework.jdbc.core.StatementCreatorUtils.setValue(StatementCreatorUtils.java:356)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:216)
at org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:127)
at org.springframework.jdbc.core.CallableStatementCreatorFactory$CallableStatementCreatorImpl.createCallableStatement(CallableStatementCreatorFactory.java:212)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:947)

编辑:

我在Spring论坛中找到了another workaround

paramSource.registerSqlType("en", Types.VARCHAR);

1 个答案:

答案 0 :(得分:0)

BeanPropertySqlParameterSource parameterSource = new BeanPropertySqlParameterSource(pojo) {
    @Override
    public Object getValue(String paramName) throws IllegalArgumentException {
        Object value = super.getValue(paramName);
        if (value instanceof Enum) {
            return value.toString();
        }

        return value;
    }
};