首页 文章

带有hibernate 4的Spring 3.1无法使用OracleTypes的存储过程

提问于
浏览
1

最近我们从hibernate 3.5升级到4.1.7以及从3.0.5升级到3.1.3 . Hibernate在 Spring 天通过jpa配置,因此不做任何更改 .

升级后,大多数东西工作正常,但使用存储过程的一个函数被破坏,但有以下异常:

java.lang.ClassCastException:$ Proxy188无法在oracle的oracle.sql.TypeDescriptor . (TypeDescriptor.java:583)的oracle.sql.TypeDescriptor.setPhysicalConnectionOf(TypeDescriptor.java:829)上转换为oracle.jdbc.OracleConnection . 位于org.springframework.jdbc.core.support.AbstractSqlTypeValue.setTypeValue(AbstractSqlTypeValue)的org.springframework.data.jdbc.support.oracle.SqlArrayValue.createTypeValue(SqlArrayValue.java:71)中的sql.ArrayDescriptor . (ArrayDescriptor.java:224) .java:58)org.springframework.jdbc.core.StatementCreatorUtils.setValue(StatementCreatorUtils.java:281)org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:217)org.springframework.jdbc . org.springframework.jdbc.core.JdbcTempl上的org.springframework.jdbc.core.CallableStatementCreatorFactory $ CallableStatementCeatorImpl.createCallableStatement(CallableStatementCreatorFactory.java:212)中的core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:128) ate.execute(JdbcTemplate.java:1008)org.springframework.jdbc.core.JdbcTemplate.call(JdbcTemplate.java:1064)org.springframework.jdbc.object.StoredProcedure.execute(StoredProcedure.java:144)

在调试模式下,我发现 AbsructSqlTypeValue.setTypeValue() 方法具有以下实现:

public final void setTypeValue(PreparedStatement ps, int paramIndex, int sqlType, String typeName)
        throws SQLException {

    Object value = createTypeValue(ps.getConnection(), sqlType, typeName);
    if (sqlType == TYPE_UNKNOWN) {
        ps.setObject(paramIndex, value);
    }
    else {
        ps.setObject(paramIndex, value, sqlType);
    }
}

这里的 ps.getConnection() 方法实际上返回一个新的Hibernate 4 LogicalConnectionImpl,它包装了真正的OracleConnection . 这就是它在Oracle驱动程序中抛出ClassCastException的原因 .

它调用oracle.SqlArrayValue的原因是因为存储过程将long列表作为输入参数 . 当定义输入参数时,我们使用 OracleTypes.ARRAY 然后在绑定值时,我们创建一个新的 SqlArrayValue 对象来包围 Long[] . 我试图直接使用泛型 Types.ArrayLong[] ,但它不能用于以下异常:

引起:java.sql.SQLException:无法转换为内部表示形式:[Ljava.lang.Long; oracle.sql.ARRAY.toARRAY(ARRAY.java:187)的@ 337f5afe位于oracle.jdbc.driver.OraclePreparedStatement . setObjectCritical(OraclePreparedStatement.java:8782)位于oracle.jdbc.driver.OracleCallableStatement的oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8278)oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8877) .setObject(OracleCallableStatement.java:4992)at theat.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:240)at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java) :39)在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)at java.lang.reflect.Method.invoke(Method.java:597)at oracle.ucp.jdbc.proxy.StatementProxyFactory.invoke(StatementProxyFact) ory.java:230)oracle.ucp.jdbc.proxy.PreparedStatementProxyFactory.invoke(PreparedStatementProxyFactory.java:124)at $ Proxy214.setObject(位于oracle.ucp.jdbc.proxy.CallableStatementProxyFactory.invoke(CallableStatementProxyFactory.java:101)在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)的sun.reflect.NativeMethodAccessorImpl.invoke0(本地方法)处于java.lang上的未知来源 . 在org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)中反映.Method.invoke(Method.java:597)

我不明白为什么jdbcTemplate以某种方式使用hibernate连接而不是本机 OracleConnection ,也许有一些配置在某处可以神奇地修复它?

1 回答

  • 0

    找到了它的根本原因 . 扩展StoredProcedure的类没有定义jdbcTemplate属性,因此使用了没有定义nativeJdbcExtractor的默认属性 . 添加jdbcTemplate依赖项以引用使用org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor定义的依赖项作为nativeJdbcExtractor解决问题 . 一世猜测hibernate 3.5 with spring 3.0没有这个问题,因为当时返回的jdbc连接已经是OracleConnection了 .

相关问题