Tomcat9.0下JdbcTemplate调用unwrap抛Not a Wrapper of OracleConnection异常
问题修复方案
根因说明
Tomcat JDBC连接池返回的连接是代理封装对象,并非原生Oracle连接,直接调用unwrap(OracleConnection.class)会因为代理层未正确透传unwrap逻辑抛出异常,同时ojdbc6与JDK1.8版本不兼容也会触发类加载、接口适配类问题。
具体解决步骤
- 第一步:升级适配的Oracle驱动包
替换当前的ojdbc6.jar为适配JDK1.8的ojdbc8.jar,同时需要保证全局只有一份ojdbc驱动:要么放在Tomcat的/lib目录下,要么放在应用的WEB-INF/lib目录下,避免两边都放置引发类加载冲突导致Wrapper识别失败。 - 第二步:修正连接解代理逻辑
需要先解开Tomcat连接池的代理层,再获取原生Oracle连接,示例代码如下:
import org.apache.tomcat.jdbc.pool.ConnectionProxy; import oracle.jdbc.OracleConnection; import java.sql.Connection; import javax.sql.DataSource; // 从JdbcTemplate获取数据源 DataSource dataSource = jdbcTemplate.getDataSource(); try (Connection poolConn = dataSource.getConnection()) { OracleConnection oracleConn; // 先判断是否是Tomcat的代理连接 if (poolConn instanceof ConnectionProxy) { // 解开代理拿到原生连接 Connection delegateConn = ((ConnectionProxy) poolConn).getDelegate(); // 再做unwrap操作 if (delegateConn.isWrapperFor(OracleConnection.class)) { oracleConn = delegateConn.unwrap(OracleConnection.class); } else { throw new RuntimeException("无法获取原生Oracle连接"); } } else if (poolConn.isWrapperFor(OracleConnection.class)) { oracleConn = poolConn.unwrap(OracleConnection.class); } else { throw new RuntimeException("当前连接不是Oracle连接代理"); } // 后续业务逻辑 ArrayDescriptor des = ArrayDescriptor.createDescriptor("XXX", oracleConn); // ... 其他操作 } catch (SQLException e) { // 异常处理逻辑 e.printStackTrace(); }
- 第三步:检查数据源配置是否被覆盖
确认Spring上下文里的数据源确实是加载的Tomcat JNDI数据源,没有被自定义的其他数据源配置覆盖,保证accessToUnderlyingConnectionAllowed="true"配置生效。
优化建议
ArrayDescriptor是Oracle JDBC旧版本废弃API,升级ojdbc8之后可以直接使用OracleConnection的createOracleArray方法直接创建数组,不需要再单独创建ArrayDescriptor,减少连接依赖逻辑。
内容的提问来源于stack exchange,提问作者srinias
相关产品推荐
相关产品推荐

