SpringBoot2中能否通过NamedParameterJdbcTemplate获取OracleDataSource?
我在Java 8、Oracle 11g(依赖ojdbc6-11.2.0.1.jar)和Gradle环境下使用Spring Boot 2,想从默认的Hikari连接池中通过NamedParameterJdbcTemplate获取OracleDataSource,但尝试失败了。
我的尝试代码:
@Repository public class MyClass{ @Autowired NamedParameterJdbcTemplate jdbcTemplate; public void myMethod(){ try{ //OracleDataSource ods = new OracleDataSource(); // 此方式可行但非Spring管理 OracleDataSource ods = (OracleDataSource) jdbcTemplate.getJdbcTemplate().getDataSource(); // 此方式失败 ods.setURL(url); ods.setUser(user); ods.setPassword(pass); ... } catch(Exception e){ System.out.println("In Exception"); e.printStackTrace(); } } }
配置文件application.properties内容:
spring.datasource.url=jdbc:oracle:thin:@//${ORA_HOST}:${ORA_PORT}/${ORA_SID} spring.datasource.username=${USER} spring.datasource.password=${PASS}
报错信息:
In Exception
java.lang.ClassCastException: com.zaxxer.hikari.HikariDataSource cannot be cast to oracle.jdbc.pool.OracleDataSource
嘿,这个类型转换异常的原因很明确——Spring Boot 2默认用HikariCP作为连接池实现,所以jdbcTemplate.getDataSource()返回的是HikariDataSource实例,它和OracleDataSource是完全不同的类,直接强转肯定会报错。下面给你几个可行的解决思路:
如果只是需要Oracle数据库连接而非数据源实例
大部分情况下,我们不需要直接操作OracleDataSource,而是需要底层的Oracle连接来执行特定操作。这种时候可以从连接池获取连接后,通过unwrap()方法拿到真实的OracleConnection:try (Connection conn = jdbcTemplate.getJdbcTemplate().getDataSource().getConnection()) { OracleConnection oracleConn = conn.unwrap(OracleConnection.class); // 在这里使用oracleConn完成你需要的操作 } catch (SQLException e) { e.printStackTrace(); }这种方式是JDBC规范推荐的,连接池的连接本质是对驱动连接的包装,
unwrap()可以安全获取底层的Oracle连接实例。确实需要OracleDataSource?替换默认连接池
如果你真的必须拿到OracleDataSource实例,可以修改Spring Boot配置,让它使用Oracle自带的数据源而非HikariCP:- 先确保Gradle依赖中排除HikariCP(如果引入了
spring-boot-starter-jdbc或spring-boot-starter-data-jpa,默认会包含Hikari); - 修改
application.properties配置:# 指定使用OracleDataSource,禁用默认的HikariCP spring.datasource.type=oracle.jdbc.pool.OracleDataSource # 保留原有数据库配置 spring.datasource.url=jdbc:oracle:thin:@//${ORA_HOST}:${ORA_PORT}/${ORA_SID} spring.datasource.username=${USER} spring.datasource.password=${PASS}
配置完成后,
jdbcTemplate.getDataSource()返回的就是OracleDataSource实例了,此时你可以安全强转。不过要注意:Oracle自带的数据源连接池性能和稳定性不如HikariCP,生产环境尽量优先用第一种方案。- 先确保Gradle依赖中排除HikariCP(如果引入了
重要提醒:不要手动修改Spring管理的数据源配置
不管用哪种方案,都别在代码里调用setURL()、setUser()这类方法修改数据源配置——Spring已经帮你完成了数据源的初始化和配置管理,手动修改会破坏Spring的生命周期管理,甚至导致连接池出现异常。如果需要调整配置,直接修改application.properties或者用配置类来实现就好。
内容的提问来源于stack exchange,提问作者DS.

