2015-09-25 100 views
0

我有一個使用Oracle數據庫的應用程序,它使用c3p0和hibernate。 升級到Hibernate 4後我得到一個異常從Oracle 10g遷移到11g驅動程序後無法打開連接

java.lang.AbstractMethodError: Method oracle/jdbc/driver/T4CPreparedStatement.setBinaryStream(ILjava/io/InputStream;J)V is abstract   at oracle.jdbc.driver.T4CPreparedStatement.setBinaryStream(T4CPreparedStatement.java) 
    at oracle.jdbc.driver.T4CPreparedStatement.setBinaryStream(T4CPreparedStatement.java) ~[ojdbc14.jar:Oracle JDBC Driver version - "10.2.0.5.0"] 
    at sun.reflect.GeneratedMethodAccessor257.invoke(Unknown Source) ~[na:na] 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_40] 
    at java.lang.reflect.Method.invoke(Method.java:497) ~[na:1.8.0_40] 
    at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.setBinaryStream(NewProxyPreparedStatement.java:2133) ~[c3p0-0.9.2.jar:0.9.2] 
    at org.hibernate.type.descriptor.sql.BlobTypeDescriptor$5$1.doBind(BlobTypeDescriptor.java:147) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.type.descriptor.sql.BlobTypeDescriptor$2$1.doBind(BlobTypeDescriptor.java:103) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.type.descriptor.sql.BasicBinder.bind(BasicBinder.java:90) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:286) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:281) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.type.AbstractSingleColumnStandardBasicType.nullSafeSet(AbstractSingleColumnStandardBasicType.java:56) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.persister.entity.AbstractEntityPersister.dehydrate(AbstractEntityPersister.java:2843) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3121) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3581) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:104) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:465) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:351) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:350) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:56) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1258) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 

所提出的解決方案是從10G升級Oracle驅動程序到11g。爲此,我用ojdbc6.jar替換了ojdbc14.jar(實際上是用於調試符號的ojdbc6_g.jar)。之後應用程序不啓動任何更多與異常

org.hibernate.exception.GenericJDBCException: Could not open connection 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:54) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:235) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.getConnection(LogicalConnectionImpl.java:171) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.doBegin(JdbcTransaction.java:67) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.begin(AbstractTransactionImpl.java:162) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.SessionImpl.beginTransaction(SessionImpl.java:1471) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
Caused by: java.sql.SQLException: Connections could not be acquired from the underlying database! 
    at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106) ~[mchange-commons-java-0.2.3.3.jar:na] 
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:677) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:134) ~[c3p0-0.9.2.jar:0.9.2] 
    at org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl.getConnection(DatasourceConnectionProviderImpl.java:139) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.internal.AbstractSessionImpl$NonContextualJdbcConnectionAccess.obtainConnection(AbstractSessionImpl.java:380) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    at org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection(LogicalConnectionImpl.java:228) ~[hibernate-core-4.3.11.Final.jar:4.3.11.Final] 
    ... 27 common frames omitted 
Caused by: com.mchange.v2.resourcepool.CannotAcquireResourceException: A ResourcePool could not acquire a resource from its primary factory or source. 
    at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1406) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:594) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:514) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutAndMarkConnectionInUse(C3P0PooledConnectionPool.java:743) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:670) ~[c3p0-0.9.2.jar:0.9.2] 
    ... 31 common frames omitted 

我看不出不從的Oracle 11g驅動程序從C3P0什麼都不是。 看來這是由於C3P0 0.9.2使用log4j的,而不是SLF4J,所以加入的log4j-過SLF4J後,我可以看到Oracle驅動程序拋出一個異常,這是C3P0記錄作爲警告(原文如此!)

WARN com.mchange.v2.resourcepool.BasicResourcePool - com[email protected]412960b2 -- Acquisition Attempt Failed!!! Clearing pending acquires. While trying to acquire a needed new resource, we failed to succeed more than the maximum number of allowed acquisition attempts (30). Last acquisition attempt exception: 
java.sql.SQLException: ORA-00604: error occurred at recursive SQL level 1 
ORA-01882: timezone region not found 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:459) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:392) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:384) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.T4CTTIfun.processError(T4CTTIfun.java:767) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.T4CTTIoauthenticate.processError(T4CTTIoauthenticate.java:450) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:539) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:235) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:382) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.T4CTTIoauthenticate.doOAUTH(T4CTTIoauthenticate.java:822) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:477) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.PhysicalConnection.<init>(PhysicalConnection.java:564) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.T4CConnection.<init>(T4CConnection.java:251) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.T4CDriverExtension.getConnection(T4CDriverExtension.java:29) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at oracle.jdbc.driver.OracleDriver.connect(OracleDriver.java:563) ~[ojdbc6_g.jar:11.2.0.4.0] 
    at com.mchange.v2.c3p0.DriverManagerDataSource.getConnection(DriverManagerDataSource.java:134) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:183) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.c3p0.WrapperConnectionPoolDataSource.getPooledConnection(WrapperConnectionPoolDataSource.java:172) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.acquireResource(C3P0PooledConnectionPool.java:188) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquire(BasicResourcePool.java:1074) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.resourcepool.BasicResourcePool.doAcquireAndDecrementPendingAcquiresWithinLockOnSuccess(BasicResourcePool.java:1061) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.resourcepool.BasicResourcePool.access$800(BasicResourcePool.java:32) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask.run(BasicResourcePool.java:1798) ~[c3p0-0.9.2.jar:0.9.2] 
    at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:636) [mchange-commons-java-0.2.3.3.jar:na] 

通過將參數-Duser.timezone=GMT提供給啓動JRE的命令可以解決此問題。但問題是爲什麼我在Linux上運行Java 8必須這樣做?我的時區正確設置:

$ date +'%:z %Z' 
+03:00 EEST 

爲什麼我必須另外設置一個變量?

+0

您是否正在使用JRE 6或以上版本? –

+0

你已經仔細檢查了你連接的11g版本(11gR1/2 +次要版本)是否有正確的'ojdbc6_g.jar'? –

+0

我可以建議的最後一件事是檢查'ojdbc6_g.jar'肯定是在應用程序的類路徑中。 –

回答

0

在客戶端,一切似乎都是正確的。 TimeZone.getDefault().getID()返回我Europe/Helsinki。但Oracle數據庫表V$TIMEZONE_NAMES不包含Europe/Helsinki,導致ORA-01882: timezone region not found異常。

一個需要申請DSTv15 Timezone Patches到DB獲得Europe/Helsinki那裏。否則,必須在客戶端明確設置-Duser.timezone=EET以避免此解決方案並遵循例外情況。

1

JDBC 11.2連接到服務器時起使用時區名(通常從OS獲得)。有很多原因可以做到這一點,主要基於避免許多與DST相關的問題,如果您使用UTC的固定偏移量進行連接。

但是,如果數據庫不明白的時區ID,那麼這個錯誤將被拋出。

有處理這個問題的各種方式,最優選的是服務器更新到版本不明白時區或使用最新的時區補丁修補現有的服務器。

備選地,更改客戶端使用或者通過在執行之前在環境設置TZ或使用-Duser.timezone = XXXX來改變它在JVM的時區。

最後,您還可以使用-Doracle.jdbc.timezoneAsRegion = false將恢復到發送連接上的固定偏移。不推薦這樣做,因爲它可能會重新引入不正確的DST相關行爲。

+0

問題DB在'V $ TIMEZONE_NAMES'中沒有'Europe/Helsinki'。 – divanov

+0

您需要修補數據庫以將「Europe/Helsinki」添加到可能的時區名稱列表中。或者,將Java語言環境時區(使用-Duser = timezone)更改爲數據庫支持的時區。 –

相關問題