Java 链接数据库与基础增删改查(CRUD)操作详解
在 Java 开发中,数据库交互是核心功能之一。无论是用户信息存储、业务数据管理,还是系统日志记录,都需要通过 Java 程序与数据库建立连接并执行操作。本文将以 MySQL 数据库为例,从环境准备、数据库连接、基础 CRUD(创建 / 读取 / 更新 / 删除)操作三个维度,手把手教你实现 Java 与数据库的交互,适合 Java 初学者入门学习。
一、环境准备:搭建基础开发环境
在编写代码前,需确保本地已配置好以下工具和依赖,避免后续出现版本兼容或依赖缺失问题。
1.1 核心工具清单
JDK | Java 程序运行和编译的基础环境 | 1.8 及以上(LTS) |
MySQL 数据库 | 提供数据存储服务的关系型数据库 | 5.7 或 8.0 |
IDE(开发工具) | 编写、调试 Java 代码(如 IntelliJ IDEA) | 社区版 / 旗舰版均可 |
MySQL JDBC 驱动 | Java 程序与 MySQL 数据库通信的桥梁 | 8.0.30(适配 MySQL 8.0) |
1.2 关键依赖配置(以 Maven 为例)
若使用 Maven 管理项目,需在 pom.xml 中添加 MySQL JDBC 驱动依赖(无需手动下载 JAR 包,Maven 会自动引入):
xml
<!-- MySQL JDBC 驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.30</version>
<scope>runtime</scope> <!-- 运行时依赖,编译时无需参与 -->
</dependency>
- 若未使用 Maven,需手动下载 MySQL JDBC 驱动 JAR 包,并在 IDE 中添加到项目的「库」中。
1.3 提前创建数据库和表
为了后续测试 CRUD 操作,我们先在 MySQL 中创建一个示例数据库和表(以「用户表 user」为例):
- 打开 MySQL 命令行或可视化工具(如 Navicat),执行以下 SQL 创建数据库:sql
- 创建「用户表 user」,包含 id(主键)、username(用户名)、age(年龄)、email(邮箱)字段:sql
二、Java 链接数据库:JDBC 核心流程
Java 通过 JDBC(Java Database Connectivity) 规范实现与数据库的连接。JDBC 本质是一套接口,由数据库厂商(如 MySQL)提供实现(即 JDBC 驱动)。
2.1 数据库连接核心步骤
- 加载 JDBC 驱动:MySQL 8.0 及以上版本无需显式加载(驱动会自动注册),低版本需通过
Class.forName("com.mysql.jdbc.Driver")加载。 - 编写连接 URL:格式为
jdbc:mysql://主机地址:端口号/数据库名?参数1&参数2。示例(MySQL 8.0):jdbc:mysql://localhost:3306/java_db?useSSL=false&serverTimezone=UTCuseSSL=false:禁用 SSL 加密(开发环境简化配置,生产环境需开启)。serverTimezone=UTC:设置时区(解决 MySQL 8.0 时区报错问题)。 - 获取数据库连接:通过
DriverManager.getConnection(url, username, password)方法,传入数据库用户名(如root)和密码(如你设置的123456)。 - 关闭资源:连接、语句、结果集使用后需关闭(避免资源泄漏),建议用
try-with-resources(自动关闭资源)。
2.2 封装连接工具类(复用代码)
为了避免重复编写连接逻辑,我们封装一个 DBUtil 工具类,提供获取连接和关闭资源的方法:
java
import java.sql.*;
/**
* 数据库连接工具类
*/
public class DBUtil {
// 数据库连接信息(根据你的本地配置修改)
private static final String URL = "jdbc:mysql://localhost:3306/java_db?useSSL=false&serverTimezone=UTC";
private static final String USER = "root"; // 你的 MySQL 用户名
private static final String PASSWORD = "123456"; // 你的 MySQL 密码
/**
* 获取数据库连接
* @return Connection 连接对象(null 表示连接失败)
*/
public static Connection getConnection() {
Connection conn = null;
try {
// MySQL 8.0 无需显式加载驱动,底层自动注册
conn = DriverManager.getConnection(URL, USER, PASSWORD);
System.out.println("数据库连接成功!");
} catch (SQLException e) {
System.out.println("数据库连接失败!");
e.printStackTrace();
}
return conn;
}
/**
* 关闭资源(Connection + Statement + ResultSet)
* @param conn 连接对象
* @param stmt 语句对象(执行 SQL 用)
* @param rs 结果集对象(查询用)
*/
public static void closeResources(Connection conn, Statement stmt, ResultSet rs) {
// 关闭顺序:ResultSet → Statement → Connection(后创建的先关闭)
try {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
// 重载:关闭无 ResultSet 的资源(如增、删、改操作)
public static void closeResources(Connection conn, Statement stmt) {
closeResources(conn, stmt, null);
}
}
测试连接是否成功:
java
public class TestDBConnection {
public static void main(String[] args) {
// 调用工具类获取连接(测试用)
Connection conn = DBUtil.getConnection();
// 关闭连接
DBUtil.closeResources(conn, null);
}
}
若控制台输出「数据库连接成功!」,说明连接配置无误。
三、基础 CRUD 操作实现
CRUD 是数据库最核心的 four 种操作,对应 Java 代码需通过 Statement 或 PreparedStatement 执行 SQL(推荐用 PreparedStatement,可避免 SQL 注入风险)。
以下所有操作均基于「user 表」,先定义一个 User 实体类(与表字段对应,封装数据):
java
/**
* User 实体类(与数据库 user 表字段对应)
*/
public class User {
private Integer id; // 对应表中 id 字段
private String username; // 对应表中 username 字段
private Integer age; // 对应表中 age 字段
private String email; // 对应表中 email 字段
// 无参构造(必要,用于反射实例化)
public User() {}
// 有参构造(除 id,因为 id 是自增的)
public User(String username, Integer age, String email) {
this.username = username;
this.age = age;
this.email = email;
}
// Getter 和 Setter 方法(用于访问和修改私有属性)
public Integer getId() { return id; }
public void setId(Integer id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public Integer getAge() { return age; }
public void setAge(Integer age) { this.age = age; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
// toString 方法(用于打印 User 对象信息)
@Override
public String toString() {
return "User{" +
"id=" + id +
", username='" + username + '\'' +
", age=" + age +
", email='" + email + '\'' +
'}';
}
}
3.1 新增操作(Create):向表中插入数据
需求:向 user 表插入一条用户数据(如 username=「张三」,age=25,email=「zhangsan@xxx.com」)。
实现代码:
java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* 新增用户操作(Create)
*/
public class UserCreate {
public static void main(String[] args) {
// 1. 获取数据库连接
Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = null;
try {
// 2. 编写 SQL(? 是占位符,避免 SQL 注入)
String sql = "INSERT INTO user (username, age, email) VALUES (?, ?, ?)";
// 3. 创建 PreparedStatement 对象(传入 SQL)
pstmt = conn.prepareStatement(sql);
// 4. 给占位符赋值(索引从 1 开始,对应 SQL 中 ? 的顺序)
pstmt.setString(1, "张三"); // 第一个 ? 赋值为 username
pstmt.setInt(2, 25); // 第二个 ? 赋值为 age
pstmt.setString(3, "zhangsan@xxx.com"); // 第三个 ? 赋值为 email
// 5. 执行 SQL(新增/删除/修改用 executeUpdate(),返回受影响的行数)
int rows = pstmt.executeUpdate();
// 6. 判断执行结果
if (rows > 0) {
System.out.println("新增用户成功!受影响行数:" + rows);
} else {
System.out.println("新增用户失败!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 7. 关闭资源
DBUtil.closeResources(conn, pstmt);
}
}
}
验证结果:打开 MySQL 可视化工具,查询 user 表,若出现「张三」的记录,则新增成功。
3.2 查询操作(Read):从表中读取数据
需求:两种常见查询场景:
- 查询单条数据:根据
id查询指定用户。 - 查询所有数据:查询
user表中所有用户。
3.2.1 查询单条数据(按 id 查询)
java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* 查询单条用户数据(Read - 按 id 查询)
*/
public class UserReadSingle {
public static void main(String[] args) {
Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null; // 存储查询结果的对象
try {
// 1. 编写 SQL(根据 id 查询)
String sql = "SELECT id, username, age, email FROM user WHERE id = ?";
// 2. 创建 PreparedStatement 并赋值
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, 1); // 查询 id=1 的用户(需确保该 id 存在)
// 3. 执行 SQL(查询用 executeQuery(),返回 ResultSet)
rs = pstmt.executeQuery();
// 4. 解析 ResultSet(判断是否有数据,并用 next() 移动指针)
if (rs.next()) {
// 根据字段名获取数据(推荐用字段名,避免字段顺序变化导致错误)
Integer id = rs.getInt("id");
String username = rs.getString("username");
Integer age = rs.getInt("age");
String email = rs.getString("email");
// 封装成 User 对象
User user = new User();
user.setId(id);
user.setUsername(username);
user.setAge(age);
user.setEmail(email);
// 打印结果
System.out.println("查询到的用户:" + user);
} else {
System.out.println("未查询到 id=1 的用户!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 关闭资源(包含 ResultSet)
DBUtil.closeResources(conn, pstmt, rs);
}
}
}
3.2.2 查询所有数据
java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* 查询所有用户数据(Read - 查全部)
*/
public class UserReadAll {
public static void main(String[] args) {
Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = null;
ResultSet rs = null;
List<User> userList = new ArrayList<>(); // 存储所有用户的集合
try {
// 1. 编写 SQL(查询所有字段)
String sql = "SELECT id, username, age, email FROM user";
// 2. 创建 PreparedStatement(无占位符,无需赋值)
pstmt = conn.prepareStatement(sql);
// 3. 执行 SQL
rs = pstmt.executeQuery();
// 4. 循环解析 ResultSet(next() 返回 false 时表示无更多数据)
while (rs.next()) {
// 封装 User 对象
User user = new User();
user.setId(rs.getInt("id"));
user.setUsername(rs.getString("username"));
user.setAge(rs.getInt("age"));
user.setEmail(rs.getString("email"));
// 添加到集合中
userList.add(user);
}
// 5. 打印结果
if (userList.isEmpty()) {
System.out.println("表中无用户数据!");
} else {
System.out.println("查询到的所有用户:");
for (User user : userList) {
System.out.println(user);
}
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.closeResources(conn, pstmt, rs);
}
}
}
3.3 更新操作(Update):修改表中数据
需求:将 id=1 的用户年龄修改为 26,邮箱修改为「**********」。
实现代码:
java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* 更新用户操作(Update)
*/
public class UserUpdate {
public static void main(String[] args) {
Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = null;
try {
// 1. 编写 SQL(修改 age 和 email,按 id 条件筛选)
String sql = "UPDATE user SET age = ?, email = ? WHERE id = ?";
// 2. 创建 PreparedStatement 并赋值
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, 26); // 第一个 ?:新年龄
pstmt.setString(2, "**********"); // 第二个 ?:新邮箱
pstmt.setInt(3, 1); // 第三个 ?:修改 id=1 的用户
// 3. 执行 SQL(用 executeUpdate())
int rows = pstmt.executeUpdate();
// 4. 判断结果
if (rows > 0) {
System.out.println("更新用户成功!受影响行数:" + rows);
} else {
System.out.println("更新失败(可能 id 不存在)!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.closeResources(conn, pstmt);
}
}
}
3.4 删除操作(Delete):删除表中数据
需求:删除 id=1 的用户数据。
实现代码:
java
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* 删除用户操作(Delete)
*/
public class UserDelete {
public static void main(String[] args) {
Connection conn = DBUtil.getConnection();
PreparedStatement pstmt = null;
try {
// 1. 编写 SQL(按 id 删除)
String sql = "DELETE FROM user WHERE id = ?";
// 2. 创建 PreparedStatement 并赋值
pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, 1); // 删除 id=1 的用户
// 3. 执行 SQL
int rows = pstmt.executeUpdate();
// 4. 判断结果
if (rows > 0) {
System.out.println("删除用户成功!受影响行数:" + rows);
} else {
System.out.println("删除失败(可能 id 不存在)!");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
DBUtil.closeResources(conn, pstmt);
}
}
}
四、常见问题与注意事项
- 连接失败报错:检查 MySQL 是否启动(Windows 用 net start mysql,Linux 用 systemctl status mysql)。确认 URL 中的「主机地址、端口号、数据库名」是否正确(默认端口 3306)。检查用户名和密码是否与本地 MySQL 配置一致。
- SQL 注入风险:严禁使用 Statement 执行动态 SQL(如 String sql = "SELECT * FROM user WHERE username = '" + username + "'"),恶意用户可通过输入 ' OR '1'='1 绕过验证。必须使用 PreparedStatement 的占位符(?)赋值,驱动会自动对参数进行转义,避免 SQL 注入。
- 资源泄漏问题:连接、Statement、ResultSet 是稀缺资源,必须关闭(即使出现异常)。推荐使用 try-with-resources 语法(Java 7+),无需手动调用 close(),示例:java
- 时区报错(MySQL 8.0):若出现 The server time zone value 'XXX' is unrecognized,需在 URL 中添加 serverTimezone=UTC 或 serverTimezone=Asia/Shanghai(国内推荐后者)。
五、进阶方向
本文讲解的是 JDBC 原生操作,实际开发中会使用更高效的框架简化代码:
- MyBatis:半自动化 ORM 框架,减少 JDBC 冗余代码,支持 XML / 注解写 SQL。
- Spring JDBC:Spring 提供的轻量级封装,核心是
JdbcTemplate,无需手动关闭资源。 - Spring Data JPA:全自动化 ORM 框架,基于 JPA 规范,无需编写 SQL(简单场景),适合快速开发。
若你已掌握本文的基础操作,可进一步学习这些框架,提升开发效率。
至此,Java 链接数据库与基础 CRUD 操作已全部讲解完毕。建议大家动手实践每一步,遇到报错时对照「常见问题」排查,逐步理解数据库交互的核心逻辑。
tl917.hsd-stone.com
eflv3.hsd-stone.com
ur1cb.hsd-stone.com
31hck.hsd-stone.com
x4uuq.hsd-stone.com
ckp18.hsd-stone.com
ydiczgjzhhd2.www.sxkjsm.com
4gt39swalf2.www.sxkjsm.com
t.www.sxkjsm.com
yosc3xw.www.sxkjsm.com
mrhr3o5k65llhf.www.sxkjsm.com
qkk21dp1zby.www.sxkjsm.com
hr5qpq7kna265.www.sxkjsm.com
kqqcdgupxpau2aw5t.sxkjsm.com
u.www.sxkjsm.com
m3bobuay.www.sxkjsm.com
ygcx.sxkjsm.com
wap.share.wuxiangxing.com
6www.share.wuxiangxing.com
mobile.shop.wuxiangxing.com
查看6道真题和解析