最近我们从 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.Array
,Long[]
但它也不起作用,但出现以下异常:
原因: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
,也许某处有一些配置可以神奇地修复它?