1.
题记:
遇到个使用Spring xml方式配置Hikari,因为一个Bean的命名原因导致爆出 SQLFeatureNotSupportedException,追溯原因过程其实很简单,但是找到问题所在确实浪费不少时间。
2.
先看源码。
由于某些原因,只能使用 Spring XML方式配置 Hikari的 datasource,我自己使用jdk 1.7版本,不过粗看了下适用1.8+的Hikari代码,应该也是存在这个问题的。
参考Hikari官方的参数配置,如果在你的xml里这么配置 Hikari的 datasource
那么,当你的程序运行到到从该dataSource取connection时候,很可能会遇到下面这样的异常:
即这个dataSource不能使用。
我先说一下解决办法:
这个异常其实是 id=”dataSource”/ref=”dataSource” 导致的,如果改一下名字,任何非 dataSource的名字,就会神奇的发现,程序正常运行了。
3.
原因呢?
看 HikariDataSource.java
发现这里并没有错,的的确确该抛异常了,所以,正常的 getConnection()不是在这个类/方法里。
实际上,正常是在 Hikari的 DriverDataSource 这个类里
那么是什么导致 DataSource使用了错误的实现类?
从HikariDataSource构造函数入口,到 getConnection 看起,追踪到 -> HikariPool(this) -> PoolBase(final HikariConfig config) -> initializeDataSource()
这里似乎看起来正常,但是,如果我们仔细看 DataSource dataSource = config.getDataSource(),也就是说 HikariConfig 其实有 get/setDataSource属性
再看看我们xml里定义的bean,bean id=”dataSource” class=”com.zaxxer.hikari.HikariDataSource”
发现没有,HikariDataSource 其实还有一个 setDataSource 属性,即我们xml里定义的 id=”dataSource” 其实还是会将自己注入给自己的!
这也就是为什么上文中 initializeDataSource 方法里,最终实例化的不是 DriverDataSource 而是自己。
所以,改一个名字就可以了。
4.
关于 SpringBoot
这令我好奇,默认支持使用Hikari作为datasource的SpringBoot是怎么实例化HikariDataSource?会有上述问题吗?
这部分代码在
不深入了,看下去,反射生成,并且未设置datasource属性,即实际是没有这个问题的。