Java MySQL 连接

JDBC(Java Database Connectivity)是 Java 访问数据库的统一标准:它定义连接、执行 SQL、处理结果等接口,由各数据库厂商提供驱动去实现。程序员只面向 JDBC API 编程,换数据库时基本不用改代码。MyBatis、Spring Data JPA 等框架底层都是 JDBC,本节内容是 Java 后端开发的地基。

JDBC 概念与驱动

  • JDBC API:java.sql 包中的接口与类,与具体数据库无关。
  • 驱动:厂商提供,负责把 JDBC 调用翻译成数据库协议,MySQL 驱动是 mysql-connector-j。
  • Maven 引入 MySQL 8 驱动:
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.0.33</version>
</dependency>

连接 URL 格式

DriverManager 通过 URL 定位数据库,格式为 jdbc:mysql://主机:端口/数据库名?参数,如: jdbc:mysql://localhost:3306/test?useSSL=false&serverTimezone=Asia/Shanghai&characterEncoding=utf8

JDBC 六步流程

固定六步:①加载驱动 ②获取连接 ③创建 Statement ④执行 SQL ⑤处理结果 ⑥释放资源。完整示例需配置环境后运行(先建好 test 库):

import java.sql.*;

public class JdbcDemo {
    public static void main(String[] args) throws Exception {
        // ① 加载驱动(8.0 驱动可自动加载,显式写更清晰)
        Class.forName("com.mysql.cj.jdbc.Driver");
        String url = "jdbc:mysql://localhost:3306/test?useSSL=false";
        // ② 建立连接
        try (Connection conn = DriverManager.getConnection(url, "root", "密码");
             Statement st = conn.createStatement()) {   // ③ 创建 Statement
            // ④ 执行 DDL:建表
            st.executeUpdate("CREATE TABLE IF NOT EXISTS user("
                    + "id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(50), age INT)");
            // ④ 执行 DML:增删改都用 executeUpdate,返回影响行数
            int rows = st.executeUpdate("INSERT INTO user(name,age) VALUES('张三',25)");
            System.out.println("插入行数:" + rows);     // 输出:插入行数:1
            // ④ 执行查询:executeQuery 返回 ResultSet
            ResultSet rs = st.executeQuery("SELECT * FROM user");
            // ⑤ 遍历结果集
            while (rs.next()) {
                System.out.println(rs.getInt("id") + " "
                        + rs.getString("name") + " " + rs.getInt("age"));
            }
        }   // ⑥ try-with-resources 自动释放连接等资源
    }
}

getInt/getString 等 getter 既可传列名,也可传列序号(从 1 开始)。

PreparedStatement 防注入

用字符串拼接 SQL 存在注入风险,如用户输入 1' OR '1'='1 会改变查询语义。PreparedStatement 用 ? 占位符预编译,参数被当纯数据处理,从根上防住注入(片段需放进带连接的方法中运行):

String sql = "SELECT * FROM user WHERE name=? AND age=?";
try (PreparedStatement ps = conn.prepareStatement(sql)) {
    ps.setString(1, "张三");   // 给第 1 个 ? 赋值
    ps.setInt(2, 25);          // 给第 2 个 ? 赋值
    try (ResultSet rs = ps.executeQuery()) {
        while (rs.next()) {
            System.out.println(rs.getString("name"));
        }
    }
}

同一 SQL 还能预编译后反复执行、批量传参,性能优于 Statement。

事务 commit/rollback

多条写操作要求"同生共死"时开启事务:全部成功才 commit,任一步失败就 rollback(片段需放进带连接的方法中运行):

conn.setAutoCommit(false);                          // 关闭自动提交 = 开启事务
try {
    st.executeUpdate("UPDATE account SET money=money-100 WHERE id=1");
    st.executeUpdate("UPDATE account SET money=money+100 WHERE id=2");
    conn.commit();                                  // 全部成功才提交
} catch (SQLException e) {
    conn.rollback();                                // 失败回滚,数据回到原样
    throw e;
}

小结:JDBC 六步流程是数据库编程骨架;增删改用 executeUpdate、查询用 executeQuery + ResultSet 遍历;防注入优先 PreparedStatement,多步写操作务必用事务 commit/rollback 保证一致性。

笔记加载中…