最近、hibernate 3.5 から 4.1.7 に、spring を 3.0.5 から 3.1.3 にアップグレードしました。Hibernate は春に jpa を介して設定されるため、変更は行われません。
アップグレード後、ほとんどのものは正常に動作しますが、ストアド プロシージャを使用する関数の 1 つが次の例外を除いて壊れています。
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. org.springframework.jdbc.core.support.AbstractSqlTypeValue.setTypeValue(AbstractSqlTypeValue.java:58) の jdbc.support.oracle.SqlArrayValue.createTypeValue(SqlArrayValue.java:71) 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) で org.springframework.jdbc.core.JdbcTemplate.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()
メソッドは実際には、実際の OracleConnection をラップする新しい Hibernate 4 LogicalConnectionImpl を返します。そのため、Oracle ドライバーで ClassCastException がスローされます。
oracle.SqlArrayValue を呼び出す理由は、ストアド プロシージャが long のリストを入力パラメータとして受け取るためです。入力パラメーターが定義されるとOracleTypes.ARRAY
、値をバインドするときに使用し、新しい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) at oracle.jdbc.driver.OracleCallableStatement.setObject(OracleCallableStatement.java:4992) at oracle.jdbc.driver.OraclePreparedStatementWrapper.setObject(OraclePreparedStatementWrapper.java:240) sun.reflect.NativeMethodAccessorImpl.invoke0(ネイティブ メソッド) で sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) で sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) java.lang.reflect.Method.invoke(Method.java:597)で oracle.ucp.jdbc.proxy.StatementProxyFactory.invoke(StatementProxyFactory.java:230)で oracle.ucp.jdbc.proxy.PreparedStatementProxyFactory.invokeで(PreparedStatementProxyFactory.java:124) at oracle.ucp.jdbc.proxy.CallableStatementProxyFactory.invoke(CallableStatementProxyFactory.java:101) at $Proxy214.setObject(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun. org.hibernate.engine で java.lang.reflect.Method.invoke(Method.java:597) で sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) で.jdbc.internal.proxy.AbstractStatementProxyHandler。continueInvocation(AbstractStatementProxyHandler.java:122)
jdbcTemplate がネイティブの代わりに休止状態接続を使用する理由がわかりませんOracleConnection
。おそらく、魔法のように修正できる設定がどこかにあるのでしょうか。