首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

JDBC 基礎核心:從驅動加載到事務隔離級別完整指南

     編輯:Java 綜合教學

前言

本文系統梳理 JDBC 核心操作,不依賴 Hibernate 或 MyBatis 等 ORM 框架,直接使用原生 JDBC 講解數據庫訪問原理。掌握這些基礎,能更透徹地理解上層框架的運行機制。

一、JDBC 環境搭建

1.1 驅動依賴配置

Maven 項目需在 pom.xml 引入 MySQL 驅動:

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.26</version>
</dependency>

1.2 數據庫連接配置

Class.forName("com.mysql.jdbc.Driver"); // 加載驅動
String url = "jdbc:mysql://localhost:3306/blog";
String username = "root";
String password = "123456";
Connection connection = DriverManager.getConnection(url, username, password);

二、SQL 執行方式對比

2.1 Statement

適用於無參數的靜態 SQL,不支持預編譯,存在 SQL 注入風險,性能較低。

2.2 PreparedStatement(推薦)

支持參數化查詢,SQL 預編譯一次可多次執行,防止 SQL 注入,性能優於 Statement。

2.3 CallableStatement

專門用於調用數據庫存儲過程。

2.4 ResultSet 結果集處理

通過 next() 方法游標遍歷查詢結果,配合 getXxx() 方法獲取列數據。

三、三大執行方法區別

方法用途返回值
executeUpdate()增刪改、DDL 操作受影響行數
executeQuery()查詢操作ResultSet
execute()複雜操作(多結果集/多更新計數)boolean

四、JDBC 封裝工具類實戰

public class JDBCHelper {
    private Connection connection;
    private PreparedStatement preparedStatement;
    
    public JDBCHelper() {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            String url = "jdbc:mysql://localhost:3306/blog";
            connection = DriverManager.getConnection(url, "root", "123456");
        } catch (Exception e) { e.printStackTrace(); }
    }
    
    /** 增刪改通用方法 */
    public int update(String sql, Object... parameters) throws SQLException {
        try {
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < parameters.length; i++) {
                preparedStatement.setObject(i + 1, parameters[i]);
            }
            return preparedStatement.executeUpdate();
        } finally {
            closeStatement();
        }
    }
    
    /** 查詢通用方法 */
    public ResultSet query(String sql, Object... parameters) throws SQLException {
        try {
            preparedStatement = connection.prepareStatement(sql);
            for (int i = 0; i < parameters.length; i++) {
                preparedStatement.setObject(i + 1, parameters[i]);
            }
            return preparedStatement.executeQuery();
        } finally {
            closeStatement();
        }
    }
    
    private void closeStatement() {
        if (preparedStatement != null) {
            try { preparedStatement.close(); } catch (SQLException e) {}
            preparedStatement = null;
        }
    }
}

五、數據庫事務深度解析

5.1 事務特性(ACID)

  • 原子性:所有操作要麼全成功,要麼全失敗回滾
  • 一致性:事務前後數據完整性保持一致
  • 隔離性:並發事務互不干擾
  • 持久性:提交後的修改永久生效

5.2 併發問題與隔離級別

隔離級別髒讀不可重複讀幻讀
READ_UNCOMMITTED可能可能可能
READ_COMMITTED避免可能可能
REPEATABLE_READ避免避免可能
SERIALIZABLE避免避免避免

現象解釋:

  • 髒讀:事務 A 讀取了事務 B 未提交的修改
  • 不可重複讀:事務 A 兩次讀取同一數據,中間事務 B 修改並提交,導致結果不一致
  • 幻讀:事務 A 按條件查詢,事務 B 插入符合條件的新數據,事務 A 再次查詢發現多出記錄

5.3 事務控制代碼實戰

public void addUserAndRole(UserBean user, UserRoleBean role) throws SQLException {
    connection.setAutoCommit(false); // 關閉自動提交
    connection.setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
    
    String userSql = "INSERT INTO b_user(name,password,level,des,tel) VALUES(?,?,?,?,?)";
    String roleSql = "INSERT INTO b_user_role(userId,roleId) VALUES(?,?)";
    
    try {
        // 插入用戶
        preparedStatement = connection.prepareStatement(userSql);
        preparedStatement.setString(1, user.getName());
        preparedStatement.setString(2, user.getPassword());
        preparedStatement.setInt(3, user.getLevel());
        preparedStatement.setString(4, user.getDes());
        preparedStatement.setString(5, user.getTel());
        preparedStatement.executeUpdate();
        
        // 模擬業務異常
        if (role.getRoleId() == 0) {
            throw new Exception("角色ID無效");
        }
        
        // 插入用戶角色關係
        preparedStatement = connection.prepareStatement(roleSql);
        preparedStatement.setInt(1, role.getUserId());
        preparedStatement.setInt(2, role.getRoleId());
        preparedStatement.executeUpdate();
        
        connection.commit(); // 提交事務
        System.out.println("執行成功");
    } catch (Exception e) {
        connection.rollback(); // 回滾事務
        System.out.println("執行失敗: " + e.getMessage());
    }
}

六、數據庫連接池

頻繁創建/銷毀連接開銷極大,生產環境必須使用連接池(如 C3P0、Druid、HikariCP)。詳細原理參考:連接池深度解析

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved