讲师中心 微信公众号
AI工具推荐 视频效率加速

java怎样连接数据库并执行 CRUD 操作 java数据库 CRUD 操作的基础教程​

夏晨大大_3785

夏晨大大_3785

发布时间:2025-08-02 13:33:01

|

453人浏览过

|

来源于php中文网

原创

加载数据库驱动,通过class.forname()显式注册jdbc驱动以确保兼容性;2. 建立数据库连接,使用drivermanager.getconnection()方法传入正确的url、用户名和密码,注意检查网络、端口及服务状态;3. 使用preparedstatement执行sql操作,通过预编译和参数绑定防止sql注入,提升安全性与性能;4. 对于增删改操作,调用executeupdate()方法并处理返回的影响行数;5. 查询操作使用executequery()获取resultset,通过while(rs.next())遍历结果集,合理使用列名或索引获取数据并处理null值;6. 将查询结果映射到java对象以提高代码可维护性;7. 使用try-with-resources语句自动关闭connection、preparedstatement和resultset,防止资源泄露;8. 在需要数据一致性的场景中手动管理事务,通过setautocommit(false)、commit()和rollback()确保操作的原子性。以上步骤完整覆盖java中jdbc连接数据库的crud操作流程及最佳实践,能够安全、高效地实现数据库交互,并有效应对常见问题如驱动加载失败、连接错误和sql注入风险,最终确保应用程序的稳定性和数据完整性。

java怎样连接数据库并执行 CRUD 操作 java数据库 CRUD 操作的基础教程​

Java连接数据库并进行增删改查(CRUD)操作,核心在于JDBC(Java Database Connectivity)API。它提供了一套标准接口,让Java程序能够与各种关系型数据库进行交互。简单来说,就是通过加载数据库驱动、建立连接、发送SQL命令、处理结果,来管理数据库里的数据。这套机制虽然有些底层,但它赋予了开发者极大的灵活性和控制力。

解决方案

要在Java中实现数据库的CRUD操作,我们通常会遵循一套相对固定的流程,围绕着

Connection
、
Statement
(或更推荐的
PreparedStatement
)和
ResultSet
这几个核心接口展开。

首先,你需要确保你的项目中已经引入了对应数据库的JDBC驱动。以MySQL为例,你需要添加

mysql-connector-java
依赖。

立即学习“Java免费学习笔记(深入)”;

1. 建立数据库连接 这是所有操作的起点。你需要数据库的URL、用户名和密码。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

public class DatabaseOperations {

    private static final String DB_URL = "jdbc:mysql://localhost:3306/mydatabase";
    private static final String USER = "root";
    private static final String PASS = "your_password"; // 请替换为你的数据库密码

    // 确保你的数据库中有一个名为 'users' 的表,结构类似:
    // CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(255), email VARCHAR(255));

    public static Connection getConnection() throws SQLException {
        // 注册JDBC驱动,对于新版JDBC(4.0+),这步通常可以省略,因为驱动会自动注册
        // 但显式加载有时能避免一些不必要的麻烦,尤其是老项目或特定环境。
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            System.err.println("JDBC Driver not found: " + e.getMessage());
            throw new SQLException("Failed to load JDBC driver.", e);
        }
        return DriverManager.getConnection(DB_URL, USER, PASS);
    }

    // ... 后续CRUD操作方法
}

2. 创建(Create - INSERT) 插入数据通常使用

PreparedStatement
,因为它能有效防止SQL注入,并提升性能。

    public static void insertUser(String name, String email) {
        String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) { // 使用try-with-resources自动关闭资源
            pstmt.setString(1, name);
            pstmt.setString(2, email);
            int rowsAffected = pstmt.executeUpdate();
            System.out.println("Inserted " + rowsAffected + " row(s).");
        } catch (SQLException e) {
            System.err.println("Error inserting user: " + e.getMessage());
        }
    }

3. 读取(Read - SELECT) 查询数据同样推荐使用

PreparedStatement
,并通过
ResultSet
遍历结果。

    public static void selectAllUsers() {
        String sql = "SELECT id, name, email FROM users";
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql);
             ResultSet rs = pstmt.executeQuery()) { // executeQuery() 用于查询
            System.out.println("\n--- All Users ---");
            while (rs.next()) { // 遍历结果集
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String email = rs.getString("email");
                System.out.println("ID: " + id + ", Name: " + name + ", Email: " + email);
            }
            System.out.println("-----------------");
        } catch (SQLException e) {
            System.err.println("Error selecting users: " + e.getMessage());
        }
    }

    public static void selectUserById(int id) {
        String sql = "SELECT id, name, email FROM users WHERE id = ?";
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setInt(1, id);
            try (ResultSet rs = pstmt.executeQuery()) {
                if (rs.next()) {
                    String name = rs.getString("name");
                    String email = rs.getString("email");
                    System.out.println("\n--- User Found (ID: " + id + ") ---");
                    System.out.println("Name: " + name + ", Email: " + email);
                    System.out.println("-----------------");
                } else {
                    System.out.println("No user found with ID: " + id);
                }
            }
        } catch (SQLException e) {
            System.err.println("Error selecting user by ID: " + e.getMessage());
        }
    }

4. 更新(Update - UPDATE) 修改数据与插入类似,也是使用

PreparedStatement
。

    public static void updateUserEmail(int id, String newEmail) {
        String sql = "UPDATE users SET email = ? WHERE id = ?";
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, newEmail);
            pstmt.setInt(2, id);
            int rowsAffected = pstmt.executeUpdate(); // executeUpdate() 用于更新、插入、删除
            System.out.println("Updated " + rowsAffected + " row(s).");
        } catch (SQLException e) {
            System.err.println("Error updating user: " + e.getMessage());
        }
    }

5. 删除(Delete - DELETE) 删除数据同样遵循

PreparedStatement
的模式。

    public static void deleteUser(int id) {
        String sql = "DELETE FROM users WHERE id = ?";
        try (Connection conn = getConnection();
             PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setInt(1, id);
            int rowsAffected = pstmt.executeUpdate();
            System.out.println("Deleted " + rowsAffected + " row(s).");
        } catch (SQLException e) {
            System.err.println("Error deleting user: " + e.getMessage());
        }
    }

    public static void main(String[] args) {
        // 简单的执行顺序演示
        insertUser("Alice", "alice@example.com");
        insertUser("Bob", "bob@example.com");
        insertUser("Charlie", "charlie@example.com");

        selectAllUsers();

        updateUserEmail(1, "alice.new@example.com");
        selectUserById(1);

        deleteUser(3);
        selectAllUsers();
    }
}

JDBC连接数据库的步骤与常见问题有哪些?

JDBC连接数据库的步骤,说起来就是那么几步:加载驱动、获取连接、然后就可以开始操作了。但真正动手的时候,总会遇到些让你抓狂的小细节。

首先,加载驱动是第一步。虽然现在很多新版本的JDBC驱动都支持SPI(Service Provider Interface),意味着你把JAR包放到classpath里,它就能自动被识别和加载,不需要

Class.forName()
这行代码。但我个人在实际项目中,尤其是在一些老旧环境或者对兼容性要求比较高的地方,还是习惯性地加上
Class.forName("com.mysql.cj.jdbc.Driver");
(或者你用的其他数据库驱动类名)。这就像是给JVM一个明确的信号:“嘿,我要用这个驱动了,你给我准备好!”如果这一步出问题,最常见的就是
ClassNotFoundException
,通常是你忘记把数据库驱动的JAR包放到项目的
lib
目录或者Maven/Gradle依赖里。

接着是获取连接,通过

DriverManager.getConnection(URL, user, password)
。这里的
URL
是个大坑,不同数据库有不同的格式,比如MySQL是
jdbc:mysql://localhost:3306/mydatabase
,PostgreSQL是
jdbc:postgresql://localhost:5432/mydatabase
。一个字母、一个端口号的错误,都能让你得到一个
SQLException
,告诉你连接失败。用户名和密码输错了,或者数据库服务没启动,防火墙挡住了端口,也都会导致连接失败。遇到
SQLException
时,别急着抱怨,先仔细检查URL、用户名、密码,以及数据库服务状态和网络连通性。

最后,也是我个人觉得非常重要的一点,是资源关闭。

Connection
、
Statement
(包括
PreparedStatement
)和
ResultSet
这些资源,用完了一定要关掉,不然会造成资源泄露,比如数据库连接池耗尽,系统性能下降。以前我们习惯用
try-finally
块来手动关闭,代码写起来比较冗长。但从Java 7开始引入的
try-with-resources
语句简直是福音!它能确保在
try
块执行完毕后,所有实现了
AutoCloseable
接口的资源都会被自动关闭。我强烈推荐你始终使用这种方式,它让代码更简洁、更健壮,大大降低了资源泄露的风险。当你看到代码里一堆
conn.close()
、
stmt.close()
、
rs.close()
,并且还嵌套在
finally
块里时,就应该考虑是不是可以重构一下了。

如何在Java中安全地执行SQL插入、更新和删除操作?

在Java中执行SQL的插入、更新和删除操作,安全性是第一位的。这里我不得不再次强调

PreparedStatement
的重要性。它不仅是提升性能的利器,更是防范SQL注入攻击的坚固盾牌。

为什么是

PreparedStatement
?

想象一下,如果你直接拼接SQL字符串,比如

"INSERT INTO users (name, email) VALUES ('" + userName + "', '" + userEmail + "')"
。如果
userName
用户输入的是
' OR '1'='1
,那么你的SQL语句就会变成
INSERT INTO users (name, email) VALUES ('' OR '1'='1', '...')
,这可能会导致意想不到的行为,甚至允许攻击者执行任意SQL命令。

PreparedStatement
的工作方式是预编译SQL语句。当你创建
PreparedStatement
时,数据库会先解析并编译带有占位符(
?
)的SQL模板,然后当你通过
setString()
、
setInt()
等方法设置参数时,这些参数是作为数据值发送给数据库的,而不是作为SQL代码的一部分。这样,即使参数中包含SQL关键字或特殊字符,它们也只会被当作普通字符串处理,从而有效地阻止了SQL注入。

操作步骤

js2java
js2java

JavaScript 到 Java 全栈翻译助手,专为前端开发者学习 Java 或快速实现后端业务逻辑而设计。当用户提到以下场景时必须使用此技能: - "帮我把这段 JS 代码转成 Java" - "用 Java 怎么写这个逻辑" - "我习惯用 JS 写,想翻译成 Java" - "教我 Java,我要写后端接...

下载
  1. 定义带占位符的SQL语句: 比如
    INSERT INTO users (name, email) VALUES (?, ?)
    。
  2. 创建
    PreparedStatement
    对象:
    conn.prepareStatement(sql)
    。
  3. 设置参数: 使用
    pstmt.setX(parameterIndex, value)
    方法,这里的
    parameterIndex
    是从1开始的。例如,
    pstmt.setString(1, "Alice")
    会把"Alice"绑定到SQL语句的第一个
    ?
    上。
  4. 执行更新: 对于插入、更新和删除操作,都使用
    pstmt.executeUpdate()
    方法。这个方法会返回一个整数,表示受影响的行数。你可以根据这个返回值来判断操作是否成功,或者有多少条记录被修改了。

事务管理

在实际应用中,特别是在涉及多个数据库操作需要保持一致性的场景(比如转账,扣钱和加钱必须同时成功或同时失败),事务管理就显得尤为关键了。JDBC默认是自动提交事务的,这意味着每执行一个

executeUpdate()
,数据库都会立即提交。如果你需要将一系列操作作为一个原子单元来处理,你需要手动控制事务:

Connection conn = null;
try {
    conn = getConnection();
    conn.setAutoCommit(false); // 关闭自动提交

    // 执行一系列操作
    // pstmt1.executeUpdate();
    // pstmt2.executeUpdate();

    conn.commit(); // 所有操作成功,提交事务
} catch (SQLException e) {
    if (conn != null) {
        try {
            conn.rollback(); // 出现异常,回滚事务
            System.err.println("Transaction rolled back.");
        } catch (SQLException ex) {
            System.err.println("Error rolling back transaction: " + ex.getMessage());
        }
    }
    System.err.println("Transaction failed: " + e.getMessage());
} finally {
    if (conn != null) {
        try {
            conn.close(); // 最终关闭连接
        } catch (SQLException ex) {
            System.err.println("Error closing connection: " + ex.getMessage());
        }
    }
}

虽然

try-with-resources
可以自动关闭资源,但在手动事务管理中,
Connection
的关闭需要放在
finally
块中,并且要先确保事务已提交或回滚。这部分代码写起来会稍微复杂一点,但它能确保数据的一致性和完整性,这是任何健壮应用都必须考虑的。

Java中查询数据库数据并处理结果集的最佳实践是什么?

查询数据库数据,也就是Read操作,是日常开发中最频繁的动作之一。在Java中,我们使用

executeQuery()
方法来执行SELECT语句,然后通过
ResultSet
对象来获取查询结果。处理结果集,看似简单,但也有不少需要注意的地方,才能做到高效、安全且不容易出错。

ResultSet
的遍历与数据获取

executeQuery()
返回的是一个
ResultSet
对象,它本质上是一个指向查询结果的游标。刚开始,这个游标是停在第一行数据之前的。你需要调用
rs.next()
方法来将游标移动到下一行。这个方法如果成功移动到下一行,就返回
true
,否则(表示已经到达结果集的末尾)返回
false
。所以,一个典型的遍历模式就是
while (rs.next()) { ... }
。

在循环内部,你可以通过列名或者列的索引来获取数据。比如

rs.getString("column_name")
、
rs.getInt("column_name")
、
rs.getDate("column_name")
等等。选择正确的数据类型方法很重要,如果你尝试用
getInt()
去获取一个字符串类型的数据,很可能会抛出
SQLException
。

// 示例:从ResultSet中获取数据
while (rs.next()) {
    int id = rs.getInt("id"); // 通过列名获取int类型数据
    String name = rs.getString("name"); // 通过列名获取String类型数据
    // 也可以通过索引获取,但列名更具可读性
    // String email = rs.getString(3); // 假设email是第三列
    System.out.println("ID: " + id + ", Name: " + name);
}

处理

null
值

数据库中的字段可能是允许

null
的。当你从
ResultSet
中获取数据时,如果某个字段的值是
null
,那么
rs.getString()
会返回
null
,而
rs.getInt()
等基本类型的方法则会返回0或者抛出异常(取决于JDBC驱动的实现和具体类型)。为了稳妥起见,尤其是对于可能为
null
的数值类型,我个人更倾向于使用对应的包装类(如
Integer
,
Double
),然后检查是否为
null
。或者,在获取基本类型后,立即调用
rs.wasNull()
来判断上一个获取操作是否返回了
null
。

// 假设有一个字段可能为null
Integer age = rs.getInt("age"); // 如果age是NULL,getInt()可能返回0
if (rs.wasNull()) { // 判断上一个获取的值是否为NULL
    age = null; // 或者设置为其他默认值
}

资源的关闭

和前面提到的CUD操作一样,

ResultSet
也属于需要关闭的资源。幸运的是,当你在
try-with-resources
语句中创建
PreparedStatement
并执行
executeQuery()
时,如果
ResultSet
也是在这个
try
块内声明的,它也会被自动关闭。这是最推荐的方式,因为它能确保资源在不再需要时被及时释放,避免潜在的内存泄露和数据库连接池耗尽问题。

try (Connection conn = getConnection();
     PreparedStatement pstmt = conn.prepareStatement(sql);
     ResultSet rs = pstmt.executeQuery()) { // ResultSet也放在这里,确保自动关闭
    // 处理结果集
} catch (SQLException e) {
    // 异常处理
}

将结果映射到Java对象

在实际项目中,我们很少直接在

while(rs.next())
循环里打印数据。更常见的做法是,将每一行数据映射到一个Java对象(POJO/Entity),然后将这些对象收集到一个列表中。这能让你的数据处理逻辑更清晰,也更容易进行后续的操作。

import java.util.ArrayList;
import java.util.List;

// 假设有一个User类
public class User {
    private int id;
    private String name;
    private String email;

    // 构造函数、getter/setter
    public User(int id, String name, String email) {
        this.id = id;
        this.name = name;
        this.email = email;
    }
    // ...
}

// 在查询方法中
public static List<User> getAllUsersAsObjects() {
    List<User> users = new ArrayList<>();
    String sql = "SELECT id, name, email FROM users";
    try (Connection conn = getConnection();
         PreparedStatement pstmt = conn.prepareStatement(sql);
         ResultSet rs = pstmt.executeQuery()) {
        while (rs.next()) {
            int id = rs.getInt("id");
            String name = rs.getString("name");
            String email = rs.getString("email");
            users.add(new User(id, name, email));
        }
    } catch (SQLException e) {
        System.err.println("Error fetching users as objects: " + e.getMessage());
    }
    return users;
}

这样做,你的业务逻辑就可以完全脱离JDBC的细节,只与

User
对象打交道,这大大提升了代码的可维护性和可读性。当你处理更复杂的查询,比如联表查询时,这种映射模式的优势会更加明显。当然,如果项目规模更大,你可能还会考虑引入ORM框架(如Hibernate、MyBatis),它们能帮你自动化完成这种映射,甚至省去你写大部分SQL语句的麻烦。但理解JDBC底层的工作原理,仍然是使用这些框架的基础。

热门AI工具

更多
豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

蛙蛙写作

一款AI论文写作工具,主要用于超级AI智能写作助手,适合需要提升相关任务效率的用户。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

Atoms
Atoms Hot

Atoms是一款AI智能体工具,第一支自动构建真实业务的 AI 团队。

Loomy
Loomy Hot

一款AI工具,主要用于科大讯飞发布的桌面级 AI 助理,比 OpenClaw 更易用、更安全!,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

4263

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

891

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

1109

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

6161

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

3023

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

6140

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

8281

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

1130

2024.04.29

Linux 新手先学哪些命令
Linux 新手先学哪些命令

Linux新手命令专题汇集终端基础、文件目录操作、文本查看、软件安装和权限管理等入门文章,帮助按实际任务练习常用命令并建立命令行操作习惯。

0

2026.10.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
dev.java 官方:Learn Java
dev.java 官方:Learn Java

共0课时 | 0人学习

Java JDBC数据库连接官方教程
Java JDBC数据库连接官方教程

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn