我什么时候需要为 jdbc 驱动程序指定 Class.forName(driverName)?

问题描述

我对何时需要在 Java 中为 JDBC 驱动程序使用 Class.forName(driverName).newInstance() 感到困惑,因为有时如果我不使用它,事情就可以正常工作。

我记得听说它不再需要,并且没有使用它,并且一切都很好......大部分。今天,我收到了:java.sql.sqlException: No suitable driver found... 错误。我做了一些研究,结果发现只有 JDBC 4.0 驱动程序会自动加载。我一直在使用 jtds 1.3.1,也就是 JDBC 3.0。

经过一些实验,我发现类路径上有两个版本的 jtds 1.3.1,一个在 Tomcat 的全局 lib 文件夹中,一个在我的 webapp 的 lib 文件夹中。

如果我离开他们两个,我必须调用 Class.forName(driverName).newInstance() 才能正常工作。我想知道的是,为什么这可以解决问题?如果这两个罐子是一样的,我不知道它是如何选择“正确”的罐子的。

此外,如果我从 webapp 的 lib 文件夹中取出 jtds jar,如果 jtds 1.3.1 不是 JDBC 4.0 驱动程序,全局 lib 文件夹中的 jar 是如何自动找到的?

解决方法

尽管 jTDS 不是 JDBC 4 驱动程序,但它确实包含 JDBC 4 中定义的必要服务定义文件(META-INF/services/java.sql.Driver),因此它实际上受自动加载驱动程序的约束。

但是,自动加载驱动程序仅适用于初始类路径上的驱动程序。以 Tomcat 为例,它们是 Tomcat 本身的 lib 目录中的驱动程序。 WEB-INF/lib 文件夹中的驱动程序不受自动驱动程序加载的影响。

当驱动程序同时位于应用程序的 Tomcat libWEB-INF/lib 中时,我无法具体回答为什么这会导致问题,但这可能是由于具有相同的多个版本类路径上的类导致错误的类或文件被加载,破坏了一些东西。

顺便说一句,没有必要使用 newInstance()。过去(20 多年前)有时建议使用有缺陷的驱动程序在实例初始值设定项中进行注册和/或有缺陷的 JVM 在使用 Class.forName 时不运行静态初始值设定项。