Class.forName 似乎仍然是必要的

Posted

技术标签:

【中文标题】Class.forName 似乎仍然是必要的【英文标题】:Class.forName still seems necessary 【发布时间】:2016-06-17 08:28:48 【问题描述】:

来自Java documentation

在以前的 JDBC 版本中,要获得连接,首先必须通过调用方法 Class.forName 来初始化 JDBC 驱动程序。

在您的类路径中找到的任何 JDBC 4.0 驱动程序都会自动加载。 (但是,您必须使用 Class.forName 方法手动加载 JDBC 4.0 之前的所有驱动程序。)

我有一个连接到 SQL Server Express 2016 的 jersey Webservice。它在 CLASSPATH 中有 sqljdbc42.jar 这是 4.2 驱动程序

但是,如果我省略了Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver") 调用,我的DriverManager.getConnection 会抛出一个SQLException(没有为jdbc:sqlserver://localhost:1433 找到合适的驱动程序; ....")

一旦我添加了Class.forName 调用,getConnection 就会开始成功。

我使用的是 Java 8。

我错过了什么?

更新:我刚刚尝试了一个命令行程序,它可以在没有forName 的情况下工作。但是,从我在本地主机上将 REST 服务作为 Tomcat 8.0 服务器运行的 Eclipse IDE 中,它不起作用。

【问题讨论】:

"...sqljdbc42.jar 这是 4.0 驱动程序" Proof here,对于任何怀疑论者。 :-) 好吧,这不是 4.0 驱动程序,是 4.2 驱动程序,但是... @T.J.Crowder 已更新 :-) 如果是这样看来微软不喜欢遵循标准 查看sqljdbc42.jar中是否有META-INF/services/java.sql.Driver文件,其内容应该是驱动的FQN即com.microsoft.sqlserver.jdbc.SQLServerDriver在这种情况下 您将驱动程序放在哪里?在 tomcat/lib 中? 【参考方案1】:

由于SPI(服务提供者接口),DriverManager 类自身初始化时,驱动程序会自动初始化。这意味着在内部它将尝试在上下文类加载器中找到任何可用的文件META-INF/services/java.sql.Driver,并且对于找到的每个文件,它将创建在文件中定义的类的实例,在这种情况下实际上是 FQN JDBC 驱动程序,这就是 JDBC 驱动程序从 JDBC 4.0 开始自动初始化的方式。

但这只有在初始化类 DriverManager 时从上下文类加载器中可用的驱动程序才有效。确保这一点的一个好方法是让您的驱动程序可从层次结构中足够高的 类加载器 获得。在你的情况下,你应该把你的驱动程序放在tomcat/lib。实际上,通过这种方式,您的驱动程序将可以从 Common CL 获得,它应该足够高。有关 Tomcat 中 CL 层次结构的更多详细信息here。

【讨论】:

以上是关于Class.forName 似乎仍然是必要的的主要内容,如果未能解决你的问题,请参考以下文章

Class.forName()用法详解

Class.forName()用法详解

Class.forName()

Java中Class.forName()用法详解

为啥是 Class.forName('database driver')?

Class.forName()用法详解