杰瑞科技汇

Java连接MySQL数据库代码如何正确编写?

第一步:环境准备

在编写代码之前,您需要准备好两样东西:

  1. MySQL 数据库服务

    • 确保您的计算机上已经安装并运行了 MySQL 数据库。
    • 创建一个用于连接的数据库和一个测试用户,您可以在 MySQL 命令行客户端中执行以下 SQL:
    -- 创建一个名为 'java_test_db' 的数据库
    CREATE DATABASE java_test_db;
    -- 创建一个新用户 'java_user',密码为 'your_password',并授予其对 'java_test_db' 的所有权限
    CREATE USER 'java_user'@'localhost' IDENTIFIED BY 'your_password';
    GRANT ALL PRIVILEGES ON java_test_db.* TO 'java_user'@'localhost';
    FLUSH PRIVILEGES;
  2. MySQL JDBC 驱动程序 (Connector/J)

    • 这是 Java 连接 MySQL 的桥梁,您需要下载它。
    • 下载地址MySQL Connector/J 官方下载页面
    • 如何选择:选择 Platform Independent (平台独立) 的 ZIP 压缩包。
    • 如何使用
      • 下载后,解压 ZIP 文件。
      • 在解压后的文件夹中,找到一个名为 mysql-connector-j-8.0.xx.jar (版本号可能不同) 的文件。
      • 将这个 JAR 文件添加到您的 Java 项目的类路径(Classpath)中。

    在不同工具中添加 JAR 的方法

    • IDE (如 IntelliJ IDEA, Eclipse):

      1. 右键点击您的项目。
      2. 选择 "Open Module Settings" (IntelliJ) 或 "Properties" (Eclipse)。
      3. 找到 "Libraries" 或 "Java Build Path" -> "Libraries"。
      4. 点击 "Add" 或 "Attach JARs...",然后选择您刚刚下载的 mysql-connector-j-8.0.xx.jar 文件。
    • Maven 项目: 在您的 pom.xml 文件中添加以下依赖项,Maven 会自动下载和管理驱动。

      <dependency>
          <groupId>com.mysql</groupId>
          <artifactId>mysql-connector-j</artifactId>
          <version>8.0.33</version> <!-- 建议使用最新稳定版 -->
      </dependency>
    • Gradle 项目: 在您的 build.gradle 文件中添加以下依赖项。

      implementation 'com.mysql:mysql-connector-j:8.0.33' // 建议使用最新稳定版

第二步:Java 连接代码示例

这里提供一个完整的、可运行的 Java 示例,包含连接、查询、插入数据和关闭资源的所有步骤。

我们将使用 JDBC 4.0+ 的标准方式,这种方式更简洁,推荐使用。

完整代码示例

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class MySQLConnector {
    // --- 数据库连接信息 ---
    // 请根据您的实际情况修改这些值
    private static final String DB_URL = "jdbc:mysql://localhost:3306/java_test_db?useSSL=false&serverTimezone=UTC";
    private static final String USER = "java_user";
    private static final String PASS = "your_password";
    public static void main(String[] args) {
        // 使用 try-with-resources 语句,可以自动关闭资源,避免内存泄漏
        try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS)) {
            System.out.println("数据库连接成功!");
            // --- 示例1:创建表并插入数据 ---
            createAndInsertData(conn);
            // --- 示例2:查询数据 ---
            queryData(conn);
        } catch (SQLException e) {
            System.err.println("数据库连接或操作失败!");
            e.printStackTrace();
        }
    }
    /**
     * 创建表并插入示例数据
     */
    private static void createAndInsertData(Connection conn) throws SQLException {
        String createTableSQL = "CREATE TABLE IF NOT EXISTS users (" +
                               "id INT AUTO_INCREMENT PRIMARY KEY," +
                               "name VARCHAR(50) NOT NULL," +
                               "email VARCHAR(50) NOT NULL UNIQUE" +
                               ")";
        // 使用 try-with-resources 自动关闭 Statement
        try (Statement stmt = conn.createStatement()) {
            System.out.println("\n--- 正在创建表 'users' ---");
            stmt.execute(createTableSQL);
            System.out.println("表 'users' 创建成功或已存在。");
            // 插入数据
            String insertSQL1 = "INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')";
            String insertSQL2 = "INSERT INTO users (name, email) VALUES ('Bob', 'bob@example.com')";
            int rowsAffected1 = stmt.executeUpdate(insertSQL1);
            int rowsAffected2 = stmt.executeUpdate(insertSQL2);
            System.out.println("插入了 " + rowsAffected1 + " 行数据。");
            System.out.println("插入了 " + rowsAffected2 + " 行数据。");
        }
    }
    /**
     * 查询并打印 'users' 表中的所有数据
     */
    private static void queryData(Connection conn) throws SQLException {
        String selectSQL = "SELECT id, name, email FROM users";
        // 使用 try-with-resources 自动关闭 Statement 和 ResultSet
        try (Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(selectSQL)) {
            System.out.println("\n--- 查询 'users' 表数据 ---");
            System.out.println("ID\tName\tEmail");
            while (rs.next()) { // 遍历结果集
                // 通过列名获取数据,更健壮
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String email = rs.getString("email");
                System.out.println(id + "\t" + name + "\t" + email);
            }
        }
    }
}

代码详解

  1. 加载驱动 (隐式)

    • 在 JDBC 4.0 之后,当 DriverManager 尝试建立连接时,它会自动在类路径中查找 META-INF/services/java.sql.Driver 文件,并加载其中指定的驱动类(如 com.mysql.cj.jdbc.Driver),我们不再需要显式地调用 Class.forName("com.mysql.cj.jdbc.Driver")
    • 如果您使用的是非常古老的 Java 版本或 JDBC 驱动,可能需要这行代码,但现在可以省略。
  2. 建立连接 (DriverManager.getConnection)

    • 这是获取连接的核心方法。
    • DB_URL:数据库的统一资源定位符。
      • jdbc:mysql://:协议和子协议。
      • localhost:3306:数据库服务器的地址和端口。
      • /java_test_db:要连接的数据库名。
      • ?useSSL=false&serverTimezone=UTC:是重要的连接参数。
        • useSSL=false:对于本地开发,可以禁用 SSL 连接以避免警告。
        • serverTimezone=UTC:指定服务器时区,避免时区不匹配的警告。
    • **USERPASS:数据库的用户名和密码。
  3. 创建语句 (Statement / PreparedStatement)

    • Statement:用于执行静态的 SQL 语句,有 SQL 注入的风险。
    • PreparedStatement强烈推荐使用,它用于执行预编译的 SQL 语句。
      • 安全性:它使用参数化查询( 占位符),可以有效地防止 SQL 注入攻击。
      • 性能:如果同一条 SQL 语句需要多次执行,数据库可以预编译它,提高执行效率。
      • 示例String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
  4. 执行查询 (executeQuery / executeUpdate)

    • executeQuery(String sql):用于执行 SELECT 查询,返回一个 ResultSet 对象。
    • executeUpdate(String sql):用于执行 INSERT, UPDATE, DELETECREATE 等不返回结果集的语句,返回一个整数,表示受影响的行数。
  5. 处理结果集 (ResultSet)

    • ResultSet 代表一个数据集,它有一个指向当前行的光标。
    • rs.next():将光标移动到下一行,如果下一行存在,则返回 true,否则返回 false,通常用 while (rs.next()) 来遍历所有数据。
    • rs.getInt("id"), rs.getString("name"):根据列名或列索引获取当前行中特定列的值。
  6. 关闭资源 (try-with-resources)

    • Connection, Statement, ResultSet 都是 JDBC 资源,它们占用数据库连接和内存。
    • 必须在使用后关闭它们,否则会导致资源泄漏。
    • try-with-resources 语句(try (Resource res = ...))是 Java 7 引入的一个特性,它会自动在 try 块结束时关闭实现了 AutoCloseable 接口(这些 JDBC 资源都实现了)的资源,这是现代 Java 中处理资源的最佳实践。

第三步:最佳实践和注意事项

  1. 使用连接池

    • 在实际应用中,频繁地创建和销毁数据库连接是非常消耗性能的。
    • 解决方案是使用连接池,连接池在启动时预先创建一组数据库连接,应用程序需要时从池中获取,用完后归还给池,而不是直接关闭。
    • 常用的连接池库有:
      • HikariCP:目前性能最好的连接池,Spring Boot 2.x 的默认选择。
      • Apache DBCP
      • C3P0
  2. 将配置信息外部化

    • 不要将数据库 URL、用户名和密码等敏感信息硬编码在 Java 代码中。
    • 应该将它们放在配置文件中(如 application.propertiesconfig.yml),然后通过代码读取,使用 java.util.Properties 类。
  3. 始终使用 PreparedStatement

    • 除非您有充分的理由,否则请始终优先使用 PreparedStatement 来执行 SQL,以防止 SQL 注入漏洞。
  4. 处理异常

    • SQLException 是受检异常,必须处理(使用 try-catchthrows)。
    • 打印堆栈跟踪 (e.printStackTrace()) 对于调试很有帮助,但在生产环境中,应该使用日志框架(如 SLF4J + Logback/Log4j2)来记录错误。
  5. 注意时区问题

    • 连接 URL 中指定 serverTimezone 是一个好习惯,可以避免很多因时区不同导致的问题,UTC 是一个通用的选择。
分享:
扫描分享到社交APP
上一篇
下一篇