从Oracle 10g迁移到11g驱动程序后无法打开连接

时间:2015-09-25 20:53:14

标签: hibernate jdbc oracle11g oracle10g c3p0

我有一个使用Oracle DB的应用程序,它使用c3p0和hibernate。 升级到Hibernate 4之后我得到了一个异常

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]

建议的解决方案是将Oracle驱动程序从10g升级到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

我从c3p0看不到任何东西,而不是Oracle 11g驱动程序。 它似乎是由于c3p0 0.9.2正在使用log4j而不是slf4j,所以在添加log4j-over-slf4j后我可以看到Oracle驱动程序抛出异常,c3p0正在记录为警告(原文如此!)

WARN  com.mchange.v2.resourcepool.BasicResourcePool - com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@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]

通过向启动JRE的命令提供参数-Duser.timezone=GMT可以解决此问题。但问题是为什么我在Linux上运行Java 8必须这样做?我的时区设置正确:

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

为什么我必须另外设置一个变量?

2 个答案:

答案 0 :(得分:1)

JDBC 11.2以后在连接到服务器时使用时区名称(通常从操作系统获得)。有很多原因可以解决这个问题,主要是为了避免在使用UTC的固定偏移量连接时发生的许多与DST相关的问题。

但是,如果数据库不理解时区id,则会抛出此错误。

有多种方法可以解决这个问题,最好的方法是将服务器更新为了解时区的版本,或使用最新的时区补丁修补现有服务器。

或者,通过在执行前在环境中设置TZ或使用-Duser.timezone = XXXX在JVM中更改它来更改客户端使用的时区。

最后,您还可以使用-Doracle.jdbc.timezoneAsRegion = false来恢复在连接上发送固定偏移量。建议不要这样做,因为它可能会重新引入不正确的DST相关行为。

答案 1 :(得分:0)

一切似乎都在客户端。 TimeZone.getDefault().getID()返回Europe/Helsinki。但是Oracle DB表V$TIMEZONE_NAMES不包含Europe/Helsinki,导致ORA-01882: timezone region not found异常。

需要将DSTv15 Timezone Patches应用于数据库以获取Europe/Helsinki。否则,必须在客户端明确设置-Duser.timezone=EET以避免此解决方案并遵循异常。