简介:这份资源是一份面向Java初学者的PDF教程,简要演示了如何使用Eclipse连接MySQL数据库。文档从安装好MySQL开始,依次说明通过命令行创建库和表、插入测试数据、下载驱动,再到项目中导入驱动依赖,并提供了验证连接和读写数据的Java示例。全流程包含建库、建表、增查数据、驱动配置、代码运行与结果查看,能帮助读者快速建立数据库编程的整体概念。资源共一个文件,类型为PDF,大小约75KB,承载的信息密度较高。当前已有10436人学习下载。除基础步骤外,资料还整理了常见的连接失败原因,如驱动类名写错、账号密码或库表名称不一致等,并且提示在正式开发中尽量采用预编译语句防止注入,使用后及时释放数据库连接。对于准备课程设计或刚接触Java数据库编程的读者,这份简明教程既能当作操作清单,也能作为排错参考,实用价值较强。
1. Eclipse连接MySQL没有想象中那么顺:先想清楚三个前提
网上讲 Eclipse 连接 MySQL 的教程很多,但照着抄一遍能直接跑通的人并不多。这份项目笔记是很老的一套操作流程:MySQL 5.1 建库建表、Eclipse 里导入 JDBC 驱动、写 Java 类验证查询、再用 PreparedStatement 批量插入数据。整套东西适合两类人:一是刚装好 MySQL 和 Eclipse、连“驱动”是什么都不太清楚的初学者;二是被ClassNotFoundException和Communications link failure卡住,想搞明白根因的从业者。需要先说明一点:原文基于 MySQL 5.1 和旧的 JDBC 驱动,类名和连接 URL 跟你现在从官网下载的新版本可能不一样。这个差异我会在第二章单独讲,别真到报错时干瞪眼。
2. 动手前的准备:装好MySQL、建好库表、挑对JDBC驱动
2.1 MySQL安装之后要确认什么:服务、命令行和root密码
原文提到的安装包是mysql-essential-5.1.51-win32,这是很早的 Windows 安装版。装完之后系统里会多出一个 MySQL 服务,正常安装并启动的话,你在命令行里敲mysql -uroot -p,输入密码就能进到mysql>提示符。这一步其实是整个流程里最简单的,但很多人会忽略一个基本事实:MySQL 没起来,后面 Eclipse 代码写得再对也白搭。
Windows 下用services.msc找到 MySQL 服务,确认状态是“已启动”;Linux 下用systemctl status mysql或service mysql status看一眼。连接不上的时候,还有一个高频报错叫ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock',这多半是 MySQL 服务没起来或者 socket 路径不对,先去把服务拉起来再说,别急着改 Java 代码。
另外,原文示例里 root 密码写的是198876。这是演示环境的密码,别原样照搬。你自己机器上装 MySQL 时设了什么密码,后面连接串里就写什么。密码错了报的是Access denied,不是“连接超时”,这个在第五章我会专门讲。
2.2 建库建表的四条命令:test库和user表是哪来的
进入 MySQL 命令行之后,原文给了四条 SQL,我按实操习惯整理一下:
CREATE DATABASE test; USE test; CREATE TABLE user (name VARCHAR(20), password VARCHAR(20)); INSERT INTO user VALUES('huzhiheng', '123456');第一条是创建test数据库。第二条USE test是把当前操作库切到test,不加这条,后面的建表语句会建到默认库里。第三条建了一张user表,只有两个VARCHAR(20)字段。第四条插入一条测试数据,这就是后面 Java 查询要读出来的内容。
表名user在真实项目里容易出问题,因为它是很多数据库的保留概念,演示可以用,生产上最好改成users或者t_user这种。字段长度也值得注意,VARCHAR(20)存英文绰绰有余,存中文时按字符算也够用,但要确认表和库的字符集是 utf8,否则中文会变成问号。这一步和后面的characterEncoding=utf8参数是配套的,少一个都会翻车。
2.3 JDBC驱动别拿错:旧类名和新驱动类名的区别
很多新手看见“导入 JDBC 驱动”这句话就直接去下载了最新版mysql-connector-java,然后拿着旧教程里的代码跑,结果在Class.forName("com.mysql.jdbc.Driver")这行报ClassNotFoundException。这不是代码抄错了,是驱动版本和类名没有对上。
| 驱动版本 | 驱动类名 | 连接URL是否需要时区参数 | 备注 |
|---|---|---|---|
| mysql-connector-java 5.x | com.mysql.jdbc.Driver | 通常不需要 | 对应 MySQL 5.x,教程里大多用这个 |
| mysql-connector-java 8.x | com.mysql.cj.jdbc.Driver | 需要serverTimezone,否则报错 | 对应 MySQL 8.x,官网现在默认给这个 |
原文环境是 MySQL 5.1,所以代码里写的是com.mysql.jdbc.Driver。你在 2024 年装 MySQL 8.0,再从官网下驱动,拿到的几乎都是 8.x 的 jar,这时类名要改成com.mysql.cj.jdbc.Driver,URL 后面还要追加上?serverTimezone=Asia/Shanghai&useSSL=false。判断方法很简单:打开 jar 包,看里面有没有com/mysql/jdbc/Driver.class,有老类名;看有没有com/mysql/cj/jdbc/Driver.class,是新版。没有对应类,Class.forName无论如何都会失败。
提示:JDBC 4.0 以后其实可以省略
Class.forName,驱动会通过 SPI 自动注册。但老项目、老教程习惯了显式加载,写上也没坏处,还能在加载失败时第一时间定位问题。
3. 把驱动挂进Eclipse项目:Build Path的三种引法与验证
3.1 先建一个普通Java项目就够了
这一步没有技术含量,但新版 Eclipse 里有个小坑。新建项目时选择Java Project,项目名可以用原文里的my,JRE 选你本机已装的 JDK 就行。在比较新的 Eclipse 版本里,创建向导会多问你一句要不要生成module-info.java,千万别勾。一旦生成这个模块描述文件,后面Class.forName和访问外部 jar 都会受到模块化限制,报一些很费解的错。
建议先把项目里自动生成的src目录利用起来,Java 类直接放在src下或默认包里。原文的两个类MysqlJdbc和Myjproject都没有写package声明,这在教学演示里没问题,但如果你放到实际项目里,最好建一个包,比如com.demo.jdbc,避免默认包里类多了互相冲突。项目建好之后,你会看到左侧Package Explorer里多了一个空白项目,下一步就是把它和驱动 jar 关联起来。
3.2 Add External JARs:右键Build Path引入驱动的正确姿势
原文写的是“右键项目 → build Path → add external Archiver”,这里有个版本记忆偏差。老版本 Eclipse 确实叫Add External Archives,后来的 Eclipse 统一叫Add External JARs...,完整路径是:
- 右键项目名
my - 选择
Build Path→Configure Build Path... - 切到
Libraries选项卡 - 点
Add External JARs... - 选中下载好的 mysql 驱动 jar,点确定
我在实际项目里更倾向于另一种做法:在项目下建一个lib目录,把 jar 丢进去,然后右键 jar 选Build Path→Add to Build Path。这样 jar 跟着项目走,换电脑、发压缩包给同事都不会丢依赖。用Add External JARs相当于引用了一个外部路径的文件,本地路径变了或 jar 被移动,Eclipse 会显示红叉,需要重新引入。
| 引jar方式 | 依赖是否跟随项目 | 适用场景 |
|---|---|---|
| Add External JARs | 否,引用外部路径 | 临时演示、本机测试 |
| 项目内lib目录 + Add to Build Path | 是,jar在项目里 | 分享源码、压缩包给别人复现 |
| Maven/Gradle依赖 | 是,自动下载 | 正规项目,但不是本资源场景 |
这份笔记对应的就是压缩包复现场景,我建议你直接用第二种方式:建lib文件夹,把 jar 放进去再Add to Build Path,这样打包发给别人的时候,对方解压后直接 Refresh 项目就能跑,不用再满世界找 jar。
3.3 引入之后怎么确认classpath没配错
引入成功最直观的反馈是:Package Explorer里项目名下面多了一个Referenced Libraries节点,展开能看到那个驱动 jar。如果你的 Eclipse 看不到这个节点,可以打开Configure Build Path...,在Libraries选项卡里检查列表里有没有刚才加的 jar。
更稳妥的验证方式是写一个最简单的类,只做一件事:加载驱动。
public class DriverCheck { public static void main(String[] args) { try { Class.forName("com.mysql.jdbc.Driver"); System.out.println("driver found"); } catch (ClassNotFoundException e) { e.printStackTrace(); } } }这段代码只验证Class.forName能不能找到驱动类,和数据库连不连得上无关。如果这里就报ClassNotFoundException,说明 jar 没进 classpath,或者驱动类名和你 jar 版本不匹配;如果这里通过了但后面连接失败,问题在连接 URL、MySQL 服务或账号上。把这个验证步骤单独拎出来,能帮你把“依赖问题”和“连接问题”干净地切开,排查效率高很多。
注意:如果你改过 jar 或手动删过
lib目录里的文件,Eclipse 不会自动刷新。选中项目按F5,或者右键 →Refresh,然后再重新运行,不然你还会对着一个已经不存在的 jar 发呆。
4. 写第一段连接代码:驱动加载、URL参数与查询结果的正确姿势
4.1 先跑通驱动加载:Class.forName在干什么
原文第一段验证程序的完整逻辑是:加载驱动 → 建立连接 → 查询 → 遍历结果集。我把它拆开看,每一段都有值得说的地方。
import java.sql.*; public class MysqlJdbc { public static void main(String args[]) { try { Class.forName("com.mysql.jdbc.Driver"); System.out.println("Success loading Mysql Driver!"); } catch (Exception e) { System.out.print("Error loading Mysql Driver!"); e.printStackTrace(); } try { Connection connect = DriverManager.getConnection( "jdbc:mysql://localhost:3306/test", "root", "198876"); System.out.println("Success connect Mysql server!"); Statement stmt = connect.createStatement(); ResultSet rs = stmt.executeQuery("select * from user"); while (rs.next()) { System.out.println(rs.getString("name")); } } catch (Exception e) { System.out.print("get data error!"); e.printStackTrace(); } } }Class.forName("com.mysql.jdbc.Driver")的作用是让 JVM 加载这个类到内存。老版本驱动在类的静态初始化代码块里做了DriverManager.registerDriver(new Driver()),所以类一旦被加载,驱动就自动注册到DriverManager,后面getConnection才能识别协议。新版本驱动其实不写这行也能工作,但保留它可以让“加载驱动”和“建立连接”两个阶段各自有明确的报错点。
这段代码有两个地方不太讲究。第一,两个try块分别捕获了异常,但第一段 catch 里写的是Exception,如果驱动类不存在,Class.forName抛的是ClassNotFoundException,它是Exception的子类,能被接住,可就地打印堆栈时你不会立刻看出“类名写错”还是“jar没引入”。我一般会把第一段单独拆成catch (ClassNotFoundException e),错误定位更直接。第二,connect用完没有关闭,测试代码无所谓,但如果你接着在这个项目里写别的功能,连接资源一直不释放会耗尽数据库连接数。
4.2 连接URL怎么拼:localhost、3306、库名和用户名密码
URL 是这整篇笔记里最容易被忽视、也最容易出错的部分。jdbc:mysql://localhost:3306/test拆开看是这几块:
| 组成块 | 值 | 说明 |
|---|---|---|
| 协议前缀 | jdbc:mysql:// | JDBC 识别 MySQL 协议的固定开头 |
| 主机地址 | localhost | 指本机,也可写127.0.0.1 |
| 端口 | 3306 | MySQL 默认端口,自己改过就写改后的端口 |
| 数据库名 | test | 必须写实际存在的库名,没有就报 unknown database |
| 用户名 | root | MySQL 账号 |
| 密码 | 198876 | 你自己环境里的密码 |
数据库名写错是个高频错误。比如你实际上建的是mydb,URL 里写test,MySQL 会直接拒绝连接,报Unknown database 'test'。解决方式和前面说的一样:先自己用命令行连进去,show databases;看清楚有哪些库,再回来改 URL。这个习惯能省掉大量“代码看着没问题但就是连不上”的排查时间。
如果你的驱动是 8.x,URL 要变成这个样子:
Connection connect = DriverManager.getConnection( "jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useSSL=false&characterEncoding=utf8", "root", "198876");这里第一个参数用?开头,后面多个参数用&连接。不少人把?拼成了&,结果是第一个参数被吞掉,时区或 SSL 相关报错依旧出现。serverTimezone指定数据库所在时区,useSSL=false关闭 SSL 加密,这一对参数几乎是为老 MySQL 配新驱动准备的标配。
4.3 查询语句与ResultSet:while(rs.next())里到底取什么
Statement stmt = connect.createStatement()创建了一个执行 SQL 的语句对象,stmt.executeQuery("select * from user")会把查询结果返回到ResultSet。rs.next()每次把游标往下移一行,第一次调用会停在第一行上,返回true就能进入循环体。
rs.getString("name")表示取当前行name这一列的值。列名必须跟表结构里的字段名完全一致,如果你建表时字段叫username,这里写name,运行时会报Column 'name' not found。另外一个常见的翻车方式是rs.getString(1),按列索引取值,这能跑,但可读性差,表结构一调整索引就变,代码就错。我建议你按列名取,并且养成习惯:ResultSet里的列名大小写不敏感,但拼写必须一致。
这段代码跑通后,控制台会依次打印两句话:Success loading Mysql Driver!和Success connect Mysql server!,随后打印一行huzhiheng。到这里,你已经完成了一次完整的“Eclipse 连 MySQL 并读取数据”闭环。很多人觉得这就结束了,其实这只是最基础的一步,真正的工程问题还在后面——比如密码是别人演示时的、表名是单数、字段字符集不对,这些坑我在下一章展开。
5. 常见排查:Eclipse连MySQL最容易翻车的五个现场
这章是血泪经验合集。我在帮同事排查这类问题的时候,发现报错就那么几种,来来回回都是同样的原因。下面五条按我实际遇到频次排序,每条按“现象 → 原因 → 解决”写清楚。
5.1 ClassNotFoundException:jar没进来还是类名不对
现象:控制台打印Error loading Mysql Driver!,堆栈里有java.lang.ClassNotFoundException: com.mysql.jdbc.Driver。
原因只有两种:一是 jar 根本没进 classpath,Build Path设置有问题;二是 jar 是 8.x 新版,你还在用旧类名,类路径里压根没有com.mysql.jdbc.Driver这个类。
解决:先确认Referenced Libraries里有没有 jar。没有就回到第三章重新引入。有就打开 jar 看看类名,或者直接改用com.mysql.cj.jdbc.Driver试一次。我自己的习惯是写一个最小的DriverCheck类只跑Class.forName,把驱动问题和连接问题彻底分开。如果你发现改类名之后不再报ClassNotFoundException,而是报时区或 SSL 相关错误,恭喜你,驱动加载已通过,进入下一关。
5.2 Communications link failure:3306端口连不上
现象:连接时长时间卡顿,最终报Communications link failure、Connection refused或Connection timed out,堆栈里常能看到connect timed out字样。
原因:MySQL 服务没启动、端口被占用、URL 里端口写错、localhost解析异常、防火墙拦截了 3306 端口。还有一个容易被忽略的原因:MySQL 启动了skip-networking选项,只允许本地 socket 连接,不监听 TCP 端口。
解决:按顺序排查。第一步,命令行执行mysql -uroot -p,能进说明服务是好的,问题在 Java 侧的网络参数;进不去说明服务没起来,先去启动服务。第二步,Windows 执行netstat -ano | findstr 3306,Linux 执行netstat -antlp | grep 3306,确认 3306 有没有监听。第三步,把 URL 里的localhost换成127.0.0.1再试一次,有些机器 localhost 解析到 IPv6 地址,而 MySQL 只监听 IPv4。这一套走完,基本能定位是 MySQL 端还是 Java 端的问题。
5.3 Access denied for user:用户名密码和空密码
现象:报java.sql.SQLException: Access denied for user 'root'@'localhost' (using password: YES)或者(using password: NO)。
原因:密码和 URL 里写的不一致;root 用户的密码本来就是空,连接串里却传了密码;MySQL 8 默认加密方式caching_sha2_password跟旧驱动不兼容;用户 hosts 限制,比如 root 只允许 localhost 登录,但你的代码从其它机器连过来。
解决:先在命令行用mysql -uroot -p验证密码到底是多少。空密码就用getConnection(url, "root", "")。如果是 MySQL 8 配 5.x 老驱动报的认证问题,要么升级驱动到 8.x,要么执行ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '你的密码';把加密方式换回来。这里提示一句:不要把教程里的密码直接抄进自己的代码,每个环境的 root 密码都不同,这属于基础但必须养成的习惯。
5.4 时区和SSL问题:新版驱动独有的玄学报错
现象:MySQL 8 配新驱动,连接时报The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized,或者一大段 SSL 连接警告,有时连接直接失败。
原因:MySQL 8 服务端默认时区未设置,驱动去读系统时区读到中文的“中国标准时间”,解析不了;SSL 问题则是 MySQL 5.1 这种老版本不支持新驱动默认的 SSL 协商。
解决:URL 后面拼接?serverTimezone=Asia/Shanghai&useSSL=false。如果你在改 URL 之后仍然报别的参数错误,检查一下是不是把?写成了&。这个错我见过太多次:第一个参数前必须是?,后面的才是&。另外,如果你不想写死Asia/Shanghai,也可以给 MySQL 手动执行SET GLOBAL time_zone = '+8:00';,但这只对当前会话有效,永久生效还得改配置文件,不如在 URL 里直接指定来得省事。
5.5 中文乱码:characterEncoding和表字符集
现象:插入中文后,用命令行查看变成????;或者 Java 读出来是一串问号。
原因:客户端连接时没声明字符集,服务端用了默认的latin1;另一种是建表时没指定CHARSET=utf8,表的默认字符集是 latin1。
解决:URL 加characterEncoding=utf8,建表语句改成CREATE TABLE user (...) ENGINE=InnoDB DEFAULT CHARSET=utf8;。这两个动作必须一起做,只改哪一边都可能有残余问题。检查数据是否正常,用SHOW CREATE TABLE user;看表的字符集,再用SELECT * FROM user;看实际存储内容。命令行里查出来是中文,Java 查出来还是乱码,那问题就在连接参数;命令行里已经是????,那就是写入的时候字符集就不对,把数据删了重建吧,别想着事后洗数据。
6. 再看一档:用PreparedStatement批量插入并回库核对数据
能连上、能查询,接下来最常见的需求就是往表里灌数据。原文用循环执行插入语句 100 次,思路没错,但写法太粗糙:每次循环都新建语句对象、交给数据库解析 SQL,很慢。工程上更常见的是用PreparedStatement的预编译特性,同一句 SQL 只解析一次,参数通过占位符反复填充。
import java.sql.*; public class BatchInsert { public static void main(String[] args) { String url = "jdbc:mysql://localhost:3306/test"; String user = "root"; String password = "198876"; try (Connection conn = DriverManager.getConnection(url, user, password)) { PreparedStatement ps = conn.prepareStatement( "INSERT INTO user (name, password) VALUES (?, ?)"); for (int i = 0; i < 100; i++) { ps.setString(1, "chongshi" + i); ps.setString(2, "bo" + i); ps.addBatch(); } int[] rows = ps.executeBatch(); System.out.println("inserted: " + rows.length); } catch (SQLException e) { e.printStackTrace(); } } }prepareStatement在创建时就把 SQL 模板发给数据库预编译,?是占位符,用setString按序号填充。addBatch把多次参数追加到同一批执行,executeBatch一次性发送给数据库,比逐条executeUpdate快不少。try-with-resources会在代码块结束后自动关闭连接和语句对象,不用手写close()。注意一点:executeBatch不会自动提交事务,严格来说要拿到conn.commit(),但 MySQL 默认autocommit=on,每批执行完就已经落库了,这里可以不加。
跑完之后回 MySQL 命令行核实一下数据到底写进去没有:
SHOW DATABASES; USE test; SELECT * FROM user;这里有个原笔记里就存在的拼写坑,show databases;很容易手滑敲成show tatabases;,MySQL 会直接报语法错误。数据核对通过,说明从建库、建表、导入驱动、写连接代码到批量插入的整条链路都是通的。从那以后,我每次搭这类演示环境都强制自己走一遍“建表确认字符集 → 驱动类名核对 → URL 参数检查 → 回库查数”四步,少一步后面都可能翻车。希望帮到你。
本文还有配套的精品资源,点击获取