杰瑞科技汇

Java如何向MySQL插入数据?

目录

  1. 环境准备
  2. 核心步骤
  3. 完整代码示例
  4. 最佳实践与高级用法
    • 使用 PreparedStatement 防止 SQL 注入
    • 批量插入以提高性能
    • 获取自增主键 ID
  5. 常见问题与解决方案

环境准备

在开始编码之前,请确保你已经准备好以下环境:

Java如何向MySQL插入数据?-图1
(图片来源网络,侵删)
  • Java 开发环境: 安装了 JDK (JDK 8 或更高版本)。
  • MySQL 数据库: 安装并运行着 MySQL 服务器。
  • MySQL 驱动: 需要将 MySQL 的 JDBC 驱动程序 (JAR 文件) 添加到你的项目中。

如何添加 MySQL 驱动?

  • Maven 项目: 在 pom.xml 文件中添加依赖,这是最推荐的方式。
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.33</version> <!-- 建议使用较新的版本 -->
    </dependency>
  • Gradle 项目: 在 build.gradle 文件中添加依赖。
    implementation 'mysql:mysql-connector-java:8.0.33'
  • 手动添加: 从 MySQL 官网 下载 JAR 文件,并将其添加到项目的类路径中。

核心步骤

在 Java 中使用 JDBC 插入数据,通常遵循以下六个核心步骤:

  1. 加载 JDBC 驱动: 使用 Class.forName() 加载 MySQL 驱动类,对于新版本的驱动(JDBC 4.0+),这一步通常是可选的,但显式写出更清晰。
  2. 建立数据库连接: 使用 DriverManager.getConnection() 方法,提供数据库 URL、用户名和密码来创建一个 Connection 对象。
  3. 创建 StatementPreparedStatement 对象:
    • Statement: 用于执行静态的 SQL 语句。
    • PreparedStatement: 强烈推荐,用于执行预编译的 SQL 语句,可以防止 SQL 注入,并且对于重复执行的语句性能更好。
  4. 执行 SQL 插入语句: 调用 StatementPreparedStatementexecuteUpdate() 方法来执行 INSERT 语句,此方法返回一个整数,表示受影响的行数。
  5. 处理结果: 检查 executeUpdate() 的返回值,以确认插入是否成功。
  6. 关闭资源: 非常重要! 按照创建的相反顺序关闭所有资源 (ResultSet, Statement, Connection),以避免数据库连接泄漏。

完整代码示例

假设我们有一个名为 employees 的表,结构如下:

CREATE DATABASE my_company;
USE my_company;
CREATE TABLE employees (
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    position VARCHAR(100),
    salary DECIMAL(10, 2),
    hire_date DATE
);

下面是一个完整的 Java 程序,向 employees 表中插入一条新记录。

Java如何向MySQL插入数据?-图2
(图片来源网络,侵删)

使用 Statement (不推荐,仅作演示)

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.Statement;
import java.sql.SQLException;
public class InsertDataWithStatement {
    // 数据库连接信息
    private static final String DB_URL = "jdbc:mysql://localhost:3306/my_company?useSSL=false&serverTimezone=UTC";
    private static final String USER = "root";
    private static final String PASS = "your_password"; // 替换为你的数据库密码
    public static void main(String[] args) {
        Connection conn = null;
        Statement stmt = null;
        try {
            // 1. 加载 JDBC 驱动 (对于 JDBC 4.0+ 可选)
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2. 建立数据库连接
            System.out.println("Connecting to database...");
            conn = DriverManager.getConnection(DB_URL, USER, PASS);
            // 3. 创建 Statement 对象
            System.out.println("Creating statement...");
            stmt = conn.createStatement();
            // 4. 执行 SQL 插入语句
            // 注意:字符串中的单引号需要转义为 ''
            String sql = "INSERT INTO employees (name, position, salary, hire_date) " +
                         "VALUES ('张三', '软件工程师', 8500.50, '2025-10-26')";
            int rowsAffected = stmt.executeUpdate(sql);
            // 5. 处理结果
            if (rowsAffected > 0) {
                System.out.println(rowsAffected + " row(s) inserted successfully.");
            }
        } catch (ClassNotFoundException e) {
            System.err.println("MySQL JDBC Driver not found.");
            e.printStackTrace();
        } catch (SQLException e) {
            System.err.println("SQL Error: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // 6. 关闭资源
            // 确保在任何情况下都会关闭资源
            try {
                if (stmt != null) stmt.close();
                if (conn != null) conn.close();
                System.out.println("Database connection closed.");
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

使用 PreparedStatement (强烈推荐)

这是更安全、更高效的写法。

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
public class InsertDataWithPreparedStatement {
    // 数据库连接信息
    private static final String DB_URL = "jdbc:mysql://localhost:3306/my_company?useSSL=false&serverTimezone=UTC";
    private static final String USER = "root";
    private static final String PASS = "your_password"; // 替换为你的数据库密码
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        try {
            // 1. 加载 JDBC 驱动
            Class.forName("com.mysql.cj.jdbc.Driver");
            // 2. 建立数据库连接
            System.out.println("Connecting to database...");
            conn = DriverManager.getConnection(DB_URL, USER, PASS);
            // 3. 创建 SQL 语句模板,使用 ? 作为占位符
            String sql = "INSERT INTO employees (name, position, salary, hire_date) VALUES (?, ?, ?, ?)";
            // 4. 创建 PreparedStatement 对象
            System.out.println("Creating prepared statement...");
            pstmt = conn.prepareStatement(sql);
            // 5. 设置参数 (索引从 1 开始)
            pstmt.setString(1, "李四");
            pstmt.setString(2, "产品经理");
            pstmt.setDouble(3, 9500.00);
            pstmt.setDate(4, new java.sql.Date(System.currentTimeMillis())); // 使用当前日期
            // 6. 执行 SQL 插入语句
            int rowsAffected = pstmt.executeUpdate();
            // 7. 处理结果
            if (rowsAffected > 0) {
                System.out.println(rowsAffected + " row(s) inserted successfully.");
            }
        } catch (ClassNotFoundException e) {
            System.err.println("MySQL JDBC Driver not found.");
            e.printStackTrace();
        } catch (SQLException e) {
            System.err.println("SQL Error: " + e.getMessage());
            e.printStackTrace();
        } finally {
            // 8. 关闭资源
            try {
                if (pstmt != null) pstmt.close();
                if (conn != null) conn.close();
                System.out.println("Database connection closed.");
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

最佳实践与高级用法

使用 PreparedStatement 防止 SQL 注入

PreparedStatement 的最大优势是它能有效防止 SQL 注入攻击,它将 SQL 语句和数据分开处理,数据库驱动会自动对 占位符设置的参数进行转义,从而确保恶意输入不会被当作 SQL 代码执行。

对比:

  • Statement (危险): sql = "INSERT ... VALUES ('" + userInput + "')"; userInput'); DROP TABLE employees; --,整个表都会被删除。
  • PreparedStatement (安全): pstmt.setString(1, userInput);,无论 userInput 是什么,它都会被当作一个字符串值,而不是 SQL 命令的一部分。

批量插入以提高性能

当需要插入大量数据时,逐条插入效率很低,使用 PreparedStatement 的批处理功能可以极大地提高性能。

Java如何向MySQL插入数据?-图3
(图片来源网络,侵删)
// ... (前面的连接代码相同)
String sql = "INSERT INTO employees (name, position, salary) VALUES (?, ?, ?)";
pstmt = conn.prepareStatement(sql);
// 关闭自动提交,开启事务
conn.setAutoCommit(false);
try {
    // 添加多个任务到批处理中
    for (int i = 1; i <= 1000; i++) {
        pstmt.setString(1, "员工_" + i);
        pstmt.setString(2, "职位_" + i);
        pstmt.setDouble(3, 5000 + i * 10);
        pstmt.addBatch(); // 将语句添加到批处理中
    }
    // 执行批处理
    int[] results = pstmt.executeBatch();
    System.out.println("Batch inserted " + results.length + " rows.");
    // 提交事务
    conn.commit();
    System.out.println("Transaction committed.");
} catch (SQLException e) {
    // 发生错误时回滚事务
    conn.rollback();
    System.err.println("Transaction rolled back.");
    e.printStackTrace();
} finally {
    // 恢复自动提交
    conn.setAutoCommit(true);
    // ... (关闭资源)
}

获取自增主键 ID

在插入数据后,通常需要获取新记录的自增主键 ID。PreparedStatement 提供了 getGeneratedKeys() 方法来实现这一点。

// ... (前面的连接代码相同)
String sql = "INSERT INTO employees (name, position) VALUES (?, ?)";
pstmt = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS); // 关键参数
pstmt.setString(1, "王五");
pstmt.setString(2, "设计师");
pstmt.executeUpdate();
// 获取生成的键
try (ResultSet generatedKeys = pstmt.getGeneratedKeys()) {
    if (generatedKeys.next()) {
        // 获取第一列 (通常是 ID)
        long newId = generatedKeys.getLong(1);
        System.out.println("New employee inserted with ID: " + newId);
    } else {
        throw new SQLException("Failed to get ID, no ID obtained.");
    }
}

常见问题与解决方案

  1. java.lang.ClassNotFoundException: com.mysql.cj.jdbc.Driver

    • 原因: MySQL 驱动 JAR 文件没有被正确添加到项目的类路径中。
    • 解决: 检查你的构建工具(Maven/Gradle)配置,或者手动确保 JAR 文件在 CLASSPATH 中。
  2. java.sql.SQLException: Access denied for user 'root'@'localhost'

    • 原因: 数据库用户名或密码错误,或者该用户没有连接到指定数据库的权限。
    • 解决: 检查 USERPASS 变量是否正确,登录 MySQL 命令行检查用户权限。
  3. java.sql.SQLException: The server time zone value '�й���ʱ��' is unrecognized or represents more than one time zone.

    • 原因: JDBC 连接 URL 中没有指定时区,而服务器和客户端的默认时区不一致。
    • 解决: 在数据库 URL 后面添加时区参数。DB_URL = "jdbc:mysql://localhost:3306/my_company?serverTimezone=UTC";
  4. java.sql.SQLException: No suitable driver found for jdbc:mysql://...

    • 原因: 驱动类没有被加载,或者 URL 格式不正确。
    • 解决: 确保 Class.forName("com.mysql.cj.jdbc.Driver"); 被执行,URL 的格式正确(jdbc:mysql://...)。
分享:
扫描分享到社交APP
上一篇
下一篇