Class.forName("com.mysql.jdbc.Driver") 没有在 jar 文件中查找该类
Posted
技术标签:
【中文标题】Class.forName("com.mysql.jdbc.Driver") 没有在 jar 文件中查找该类【英文标题】:Class.forName("com.mysql.jdbc.Driver") is not looking in jar file for the class 【发布时间】:2020-11-18 04:04:21 【问题描述】:我是 Java 新手,学习曲线陡峭。我有一个旧的 ColdFusion 10 应用程序,我希望逐步使用 Java 类而不是 ColdFusion CFC 作为迁移出 CF 领域的一种方式。我可以让所有这些都适用于我迄今为止编写的课程。
我现在要测试如何使用 CF 正在使用的相同 java 连接器与 mysql 数据库交互(在这种情况下为 mysql-connector-java-commercial-5.1.25-bin.jar,如使用在我的本地开发机器上)。
为了测试简单起见,我的测试类和连接器 jar 都在同一个文件夹中(Windows 机器)。
问题在于这个声明:Class.forName("com.mysql.jdbc.Driver");
- 我收到的是Exception in thread "main" java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
。
现在,如果我解压缩连接器 jar,使文件夹出现在我的测试文件夹中:com\mysql\jdbc\Driver.class
(以及 jar 中的所有其他文件),我的测试类工作正常并且记录被插入我的数据库表。酷!
但是,如果我删除了实际的文件夹并依赖于 jar 本身,我就会得到 ClassNotFoundException。
在我的其他学习/测试中(使用我自己生成的 jar 文件),正在从 jar 中提取一个相关的类。但是对于这个 mysql 测试的这个特定的 jar,它不是。
我应该注意什么 - 显然我错过了什么?
谢谢。我真的很期待进入 Java 领域。 :-)
穆雷
【问题讨论】:
您是在编写一个普通的 Java 应用程序,还是一个使用 JSP 或 Servlet 等的 Web 应用程序?也就是说,您使用的是 Jetty 或 Tomcat 或 Glassfish 等 servlet 容器吗? 谢谢。纯香草。没有依赖关系。基本上是一个概念验证(对于我的编程技能和其他任何东西一样多;-)) 使用Class.forName
加载 JDBC 驱动程序自 2006 年 Java 6 发布以来已过时。此外,请使用 Maven 或 Gradle;这是他们的工作。
是的。这就是我现在需要使用的版本。请参阅下面的评论。谢谢。
【参考方案1】:
在当前目录中拥有 JAR 文件是不够的。您必须告诉 java 将 mysql jar 文件包含在 classpath
中。这可以通过在 java 命令行中使用-cp
参数或CLASSPATH
环境变量来指定。
【讨论】:
谢谢。我确实看到了其他类似的答案,但无法使其发挥作用。当使用文件夹结构(不是 jar)运行时,我这样做:C:\mypath\JavaTest\mySqlTest>java MySQLAccessMain
有效。我尝试使用java -classpath etc
,但显然语法错误。那么,请问应该怎么做? C:\mypath\JavaTest\mySqlTest>java -classpath mysql-connector-java-commercial-5.1.25-bin.jar MySQLAccessMain
throws Error: Could not find or load main class MySQLAccessMain
和我各种尝试正确的路径都失败了。 :-(
使用java -classpath .;mysql-connector-java-commercial-5.1.25-bin.jar MySQLAccessMain
。这 ”。;”在开始时告诉 java 也在当前目录中搜索 .class
文件,这是它将找到 MySQLAccessMain
的位置。
就是这样!非常感谢!我将在下面发布其他 CF 难民的完整答案。 ;-)
其实这只是一个“Java 101”问题:如何在运行时类路径中添加外部库。
是的,我确定,而且我只有 2 天,所以我在 Java 100 上,我想。 ;-) 通过研究如何在 ColdFusion 环境中进行操作变得更加复杂。谢谢!【参考方案2】:
我使用Postgres 和H2 而不是MySQL。所以我不确定你的问题可能是关于 MySQL 的。但是我现在能够使用在运行时提供的 MySQL 驱动程序创建一个新项目。请继续阅读以遵循我的示例。
Maven 驱动的项目示例
如今的 Java 项目通常由 dependency management 和 build automation 工具管理,例如 Maven、Gradle 或 Ivy。
我使用 Maven Quickstart Archetype 开始了一个新的 Java 项目。
在该原型提供的POM file 中,我做了两处更改:
将<maven.compiler.source>
和 <maven.compiler.target>
从 1.7
更改为 11
以使用 Java 11,即当前的 long-term support 版本。
为您提到的 JDBC 驱动程序添加了一个依赖项:
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
然后我在App
类的main
方法中添加了一行。
try
Class.forName("com.mysql.jdbc.Driver");
System.out.println("Found class for JDBC driver.");
catch ( ClassNotFoundException e )
e.printStackTrace();
System.out.println( "Hello World!" );
当我运行它时,没有抛出异常。所以似乎成功找到了这个类。
完整的 POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns = "http://maven.apache.org/POM/4.0.0"
xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>work.basil.example</groupId>
<artifactId>jdbc-driver-in-jar</artifactId>
<version>1.0-SNAPSHOT</version>
<name>jdbc-driver-in-jar</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.22</version>
</dependency>
</dependencies>
<build>
<pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
<plugins>
<!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<version>3.1.0</version>
</plugin>
<!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
</plugin>
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.1</version>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<artifactId>maven-install-plugin</artifactId>
<version>2.5.2</version>
</plugin>
<plugin>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.8.2</version>
</plugin>
<!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
<plugin>
<artifactId>maven-site-plugin</artifactId>
<version>3.7.1</version>
</plugin>
<plugin>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>3.0.0</version>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>
完整的应用类:
package work.basil.example;
/**
* Hello world!
*
*/
public class App
public static void main( String[] args )
try
Class.forName("com.mysql.jdbc.Driver");
System.out.println("Found class for JDBC driver.");
catch ( ClassNotFoundException e )
e.printStackTrace();
System.out.println( "Hello World!" );
一些注意事项:
我在控制台输出中注意到特定的 JDBC driver 已过时。您应该调查一下现在要使用的正确 JDBC 驱动程序。
加载类
com.mysql.jdbc.Driver'. This is deprecated. The new driver class is
com.mysql.cj.jdbc.Driver'。驱动通过SPI自动注册,一般不需要手动加载驱动类。
Class.forName
是加载 JDBC 驱动程序的老式方法,不再需要。几年前,JDBC 驱动程序加载得到了很大改进。今天的 JDBC 驱动程序是通过 Java 的 Service Provider Interface (SPI) 工具加载的。但是 Class.forName
代码可能仍然有助于探索您的这个问题,以验证可以在您的 classpath 上找到该课程。
通常最好使用DataSource
来获取数据库连接。您的 JDBC 驱动程序可能提供了DataSource
的实现。此类将保存与数据库服务器建立连接所需的信息,例如查找数据库服务器的地址,以及用于向数据库服务器进行身份验证的用户名和密码。
【讨论】:
哇!感谢罗勒的详细回答。我使用旧版 mysql 连接器的原因是我的 ColdFusion 主机公司只提供 CF10 和 Java 1.6。有大量的 CFC 文件,我无法一次将它们全部转换为 Java。由于 CF 是在 Java 上构建的,因此可以混合搭配 CF 和 Java,所以我的想法是使用我所拥有的(Java 1.6)并将业务逻辑逐步转换为 Java 类,直到我达到放弃 CF 的地步完全使用 Java 完成所有工作。那时我可以升级到现代工具。 :-) @Murrah 顺便说一句,我喜欢使用 Vaadin.com 在服务器端用纯 Java 构建 Web 应用程序,以便在标准 Web 技术(HTML、CSS、javascript)上自动呈现 UI客户端。 谢谢,我去看看【参考方案3】:好的。感谢您所有快速、有用和有趣的输入! :-)
两件事:
使用来自@schtever 的java
答案运行:java -classpath .;mysql-connector-java-commercial-5.1.25-bin.jar MySQLAccessMain
。我不知道.;
语法。谢谢。
由于我最终将在 ColdFusion 上下文中执行该类(至少现在是这样),因此以下 CFM 可以正常工作,因为当然,ColdFusion 会处理指向其 jar 堆的类路径。
这是java测试类
public class MySQLAccessMain
public static void main(String[] args) throws Exception
MySQLAccess dao = new MySQLAccess();
dao.readDataBase(); // Run some fixed SELECT and INSERT tests
这是 CFM 版本
var dao = createObject("java","MySQLAccess");
dao.readDataBase();
当然还有 application.cfc:
this.javaSettings =
loadPaths: [
"/myjava" // Where MySQLAccess.class goes
]
,loadColdFusionClassPath: true // If this is true you can also use the coldfusion builtin java classes
,reloadOnChange = true
,watchInterval = 2
;
:-) 快乐的露营者!再次感谢。
【讨论】:
最后一条评论 - 分号取决于平台。在 *nix 系统上,它是一个冒号。另外,我可以要求您接受我的回答吗?谢谢! 再次感谢。完毕。对不起,我以为我接受了。非常感谢。以上是关于Class.forName("com.mysql.jdbc.Driver") 没有在 jar 文件中查找该类的主要内容,如果未能解决你的问题,请参考以下文章
为啥我找不到 Class.forName("com.mysql.jdbc.Driver"); 的异常[复制]
h2 数据库的 ClassNotFound 异常 class.forname("org.h2.Driver")
连接数据库时 Class.forName("oracle.jdbc.driver.OracleDriver") 的实际用途是啥?
Class.forName("com.mysql.jdbc.Driver").newInstance()