2012-11-06 29 views
1

最近我們從休眠3.5升級到4.1.7,以及從春季到3.0.5 3.1.3程序。 Hibernate在spring中通過jpa進行配置,因此不做任何更改。春3.1休眠4不能使用存儲與OracleTypes

升級後,大部分的東西工作正常,但使用存儲過程一個功能與以下異常折斷

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) 在org.springframework.jdbc.core.support.AbstractSqlTypeValue.setTypeValue(AbstractSqlTypeValue.java:58) 在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.core.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()方法在這裏實際上返回一個新的Hibernate 4包含真正OracleConnection的LogicalConnectionImpl。這就是爲什麼它在Oracle驅動中拋出ClassCastException。

爲什麼它調用oracle.SqlArrayValue的原因是因爲在存儲過程採用多頭作爲輸入參數列表。當定義輸入參數,我們使用OracleTypes.ARRAY然後邊結合的值,我們創建一個新對象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(本機方法) 在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) 在oracle.ucp.jdbc.proxy.CallableStatementProxyFactory.invoke(CallableStatementProxyFactory.java:101) 在$ Proxy214.setObject(來源不明) 在sun.reflect.NativeMethodAccessorImpl.invoke0(本機方法) 在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 在JAV a.lang.reflect.Method.invoke(Method.java:597) 在org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)

我不理解爲什麼jdbcTemplate以某種方式使用hibernate連接而不是本地OracleConnection,也許有一些配置在某處可以神奇地修復它?

回答

0

找到它的根本原因。擴展StoredProcedure的類沒有定義jdbcTemplate屬性,因此使用默認的沒有定義nativeJdbcExtractor的類。在添加jdbcTemplate依賴項以將與org.springframework.jdbc.support.nativejdbc.CommonsDbcpNativeJdbcExtractor一起定義的那個引用爲nativeJdbcExtractor後,解決該問題。我猜Spring 3.0的hibernate 3.5沒有這個問題,因爲那時返回的jdbc連接已經是OracleConnection了。