1

最近我们从 hibernate 3.5 升级到 4.1.7 以及 spring 从 3.0.5 到 3.1.3。Hibernate 是在 spring 中通过 jpa 配置的,因此没有进行任何更改。

升级后,大部分东西都可以正常工作,但是使用存储过程的一个函数被破坏了,但有以下例外:

java.lang.ClassCastException:$Proxy188 无法转换为 oracle.jdbc.OracleConnection
在 oracle.sql.TypeDescriptor.setPhysicalConnectionOf(TypeDescriptor.java:829) 在 oracle.sql.TypeDescriptor.(TypeDescriptor.java:583) 在 oracle.sql.ArrayDescriptor.(ArrayDescriptor.java:224) 在 org.springframework.data。 jdbc.support.oracle.SqlArrayValue.createTypeValue(SqlArrayValue.java:71) at org.springframework.jdbc.core.support.AbstractSqlTypeValue.setTypeValue(AbstractSqlTypeValue.java:58) at org.springframework.jdbc.core.StatementCreatorUtils.setValue( StatementCreatorUtils.java:281) 在 org.springframework.jdbc.core.StatementCreatorUtils.setParameterValueInternal(StatementCreatorUtils.java:217) 在 org.springframework.jdbc.core.StatementCreatorUtils.setParameterValue(StatementCreatorUtils.java:128) 在 org.springframework.jdbc 。核。CallableStatementCreatorFactory$CallableStatementCeatorImpl.createCallableStatement(CallableStatementCreatorFactory.java:212) at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:1008) at 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在绑定值时使用 then ,我们创建一个新SqlArrayValue对象来包裹Long[]. 我尝试直接使用泛型Types.ArrayLong[]但它也不起作用,但出现以下异常:

原因:java.sql.SQLException:无法转换为内部表示:[Ljava.lang.Long;@337f5afe
在 oracle.sql.ARRAY.toARRAY(ARRAY.java:187) 在 oracle.jdbc.driver.OraclePreparedStatement.setObjectCritical(OraclePreparedStatement.java:8782) 在 oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8278) 在oracle.jdbc.driver.OraclePreparedStatement.setObjectInternal(OraclePreparedStatement.java:8877) 在 oracle.jdbc.driver.OracleCallableStatement.setObject(OracleCallableStatement.java:4992) 在 oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:240)在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 oracle.ucp.jdbc.proxy.StatementProxyFactory.invoke(StatementProxyFactory.java:230) 在 oracle.ucp.jdbc.proxy.PreparedStatementProxyFactory.invoke 的 java.lang.reflect.Method.invoke(Method.java:597) (PreparedStatementProxyFactory.java:124) 在 oracle.ucp.jdbc.proxy.CallableStatementProxyFactory.invoke(CallableStatementProxyFactory.java:101) 在 $Proxy214.setObject(Unknown Source) 在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 在 sun。 reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在 java.lang.reflect.Method.invoke(Method.java:597) 在 org.hibernate.engine .jdbc.internal.proxy.AbstractStatementProxyHandler。continueInvocation(AbstractStatementProxyHandler.java:122)

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

4

1 回答 1

0

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

于 2012-11-08T06:10:31.360 回答