文件名称 | 版本号 | 作者 | 版本 | |
---|---|---|---|---|
解决金仓数据源报:Caused by: java.lang.ClassNotFoundException: com.kingbase.Driver | v1.0.0 | 学生宫布 | 8416837 | SpringBoot 2.2.6 SpringCloud Hoxton.SR4 |
备注:这个问题是自定义代码bug,网上可能没有多少人遇到这个问题
报错全称
Caused by: java.lang.ClassNotFoundException: com.kingbase.Driver
at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at com.alibaba.druid.util.JdbcUtils.createDriver(JdbcUtils.java:674)
... 161 common frames omitted
java.sql.SQLException: com.kingbase.Driver
at com.alibaba.druid.util.JdbcUtils.createDriver(JdbcUtils.java:676)
at com.alibaba.druid.pool.DruidDataSource.resolveDriver(DruidDataSource.java:1203)
at com.alibaba.druid.pool.DruidDataSource.init(DruidDataSource.java:878)
代码
druid 已编译的↓
// this.driverClass是字符串
this.driverClass = JdbcUtils.getDriverClassName(this.jdbcUrl);
...
this.driver = JdbcUtils.createDriver(this.driverClassLoader, this.driverClass);
...
public static Driver createDriver(ClassLoader classLoader, String driverClassName) throws SQLException {
Class<?> clazz = null;
if (classLoader != null) {
try {
clazz = classLoader.loadClass(driverClassName);
} catch (ClassNotFoundException var8) {
}
}
if (clazz == null) {
try {
ClassLoader contextLoader = Thread.currentThread().getContextClassLoader();
if (contextLoader != null) {
clazz = contextLoader.loadClass(driverClassName);
}
} catch (ClassNotFoundException var7) {
}
}
if (clazz == null) {
try {
clazz = Class.forName(driverClassName);
} catch (ClassNotFoundException var6) {
throw new SQLException(var6.getMessage(), var6);
}
}
...
产生的原因
因为没有获取传来的驱动类,所以就根据数据源分配驱动:
分配的驱动不正确,——根据源码(编译版)可知:
druid↓ 注意倒数第二行
// 获取驱动
public static String getDriverClassName(String rawUrl) throws SQLException {
...
} else if (!rawUrl.startsWith("jdbc:kingbase:") && !rawUrl.startsWith("jdbc:kingbase8:")) {
if (rawUrl.startsWith("jdbc:gbase:")) {
return "com.gbase.jdbc.Driver";
} else if (rawUrl.startsWith("jdbc:xugu:")) {
return "com.xugu.cloudjdbc.Driver";
} else if (rawUrl.startsWith("jdbc:hive:")) {
return "org.apache.hive.jdbc.HiveDriver";
} else if (rawUrl.startsWith("jdbc:hive2:")) {
return "org.apache.hive.jdbc.HiveDriver";
} else if (rawUrl.startsWith("jdbc:phoenix:thin:")) {
return "org.apache.phoenix.queryserver.client.Driver";
} else if (rawUrl.startsWith("jdbc:phoenix://")) {
return "org.apache.phoenix.jdbc.PhoenixDriver";
} else if (rawUrl.startsWith("jdbc:kylin:")) {
return "org.apache.kylin.jdbc.Driver";
} else if (rawUrl.startsWith("jdbc:elastic:")) {
return "com.alibaba.xdriver.elastic.jdbc.ElasticDriver";
} else if (rawUrl.startsWith("jdbc:clickhouse:")) {
return "ru.yandex.clickhouse.ClickHouseDriver";
} else if (rawUrl.startsWith("jdbc:presto:")) {
return "com.facebook.presto.jdbc.PrestoDriver";
} else if (rawUrl.startsWith("jdbc:inspur:")) {
return "com.inspur.jdbc.KdDriver";
} else if (rawUrl.startsWith("jdbc:polardb")) {
return "com.aliyun.polardb.Driver";
} else {
throw new SQLException("unknown jdbc driver : " + rawUrl);
}
} else {
return "com.kingbase.Driver";
}
上述代码很明显,以jdbc:kingbase:
或jdbc:kingbase8:
开头的数据源返回"com.kingbase.Driver"
但是"com.kingbase.Driver"这个类在项目是不存在的,试用的是8版本,所以报错了。因为试用的是kingbase8,驱动类应该是:com.kingbase8.Driver
弯路、坑
找源码是没错的,但这里有个误区,源码返回"com.kingbase.Driver"是因为连接池底层没能获取上层传的driverClassName键,因为key值使用了横线写法,而不是小驼峰↓
这个driverClassName是自定义的配置,进入druid之前,会经过一定解析,按道理,横线写法也是可以识别的,进入底层之前的解析疑似有bug。
分析
因为没传驱动类,导致自动分配的驱动类不合适,看看最新源码吧,
找到源码,发现最新提交是12天前:
但是此次提交注释与kingbase8无关,点进去看看再说,
那么,根据druid的源码,如果不传驱动类,则分配驱动类"com.kingbase.Driver"
解决方案
1)将driver-class-name改为driverClassName
领悟
如果很蹊跷,八成是低级错误
关于
若交流技术,请联系qq:8416837