1. 程式人生 > >MySQL學習筆記(4)-- jdbc異常處理和工具類抽取

MySQL學習筆記(4)-- jdbc異常處理和工具類抽取

一:異常處理

在前面的學習中,所有的異常全部都是使用throws方法解決的,現在嘗試將異常在程式內部進行處理。 為什麼要在程式內部處理異常? 因為採用throws方法,一旦產生異常,程式會停止執行,並將異常丟擲,但是此時程式內的資源並沒有釋放出來,而Connection物件資源是非常寶貴的,所以要使用try…catch…finally語句在程式內部處理異常,即使異常產生了,也能保證資源被釋放

解決思路依然是四個步驟 1、連線驅動 2、獲取連線 3、處理資料 4、釋放資源

實現程式碼:

@Test
    public void test_jdbc() {
        // 1. 裝載驅動
try { Class.forName("com.mysql.jdbc.Driver"); } catch (ClassNotFoundException e) { e.printStackTrace(); throw new RuntimeException("驅動載入失敗!"); } Connection conn = null; Statement stmt = null; ResultSet rs = null; try
{ // 2. 建立連線 conn = DriverManager.getConnection("jdbc:mysql:///mydb", "root", "123"); // 3. 操作資料 String sql = "select * from user;"; stmt = conn.createStatement(); rs = stmt.executeQuery(sql); while (rs.next()) { int
id = rs.getInt("id"); String username = rs.getString("username"); String password = rs.getString("password"); String email = rs.getString("email"); System.out.println(id + " : " + username + " : " + password + " : " + email); } } catch (SQLException e) { e.printStackTrace(); } finally { // 4. 釋放資源 if (rs != null) { try { rs.close(); } catch (SQLException e) { e.printStackTrace(); } rs = null; } if (stmt != null) { try { stmt.close(); } catch (SQLException e) { e.printStackTrace(); } stmt = null; } if (conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } conn = null; } } }

二 :工具類抽取

通過前面的學習,發現通過Java程式對資料庫進行訪問的時候,無論進行什麼操作,總體來說就是載入驅動獲取連線處理資料釋放資源這四個步驟。 其中,除了操作資料這個步驟不同之外,其他三個步驟都是一樣的,考慮將程式碼提取出來進行封裝,提高程式碼的複用性

實現方法: 將載入驅動、獲取連線、釋放資源三個所有操作共有的方法包裝成一個工具類,將方法都定義成靜態方法,使用的時候直接通過類名呼叫。

實現程式碼: 工具類:JDBCUtils


import java.sql.*;

// 硬編碼 : 將資料寫死在 `類` 中, 而不是將資料寫在配置檔案中.

public class JDBCUtils {
    // 屬性 (資料)
    private static final String driverClass = "com.mysql.cj.jdbc.Driver";
    private static final String url = "jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&characterEncoding=UTF-8";
    private static final String username = "root";
    private static final String password = "123456";


    // 1. 載入驅動
    public static void loadDriver() {
        try {
            Class.forName(driverClass);
        } catch (ClassNotFoundException e) {
            // 說明 : 如果驅動載入失敗, 之後的所有操作就無需繼續執行了...
            throw new RuntimeException("驅動載入失敗!");
        }
    }

    // 2. 獲取連線
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }

    // 3. 釋放資源
    public static void release(Connection conn, Statement stmt, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;  // clear to let GC do its work
        }

        // 呼叫下面的方法實現 conn, stmt
        release(conn, stmt);
    }

    public static void release(Connection conn, Statement stmt) {

        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            stmt = null;
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn = null;
        }
    }
}

測試類

@Test
public void test1() {

    // 1. 載入驅動
    JDBCUtils.loadDriver();

    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;

    try {
        // 2. 獲取連線
        conn = JDBCUtils.getConnection();
        // 3. 操作資料
        String sql = "select * from user where id < 10;";
        stmt = conn.createStatement();
        rs = stmt.executeQuery(sql);
        while (rs.next()) {
            int id = rs.getInt("id");
            String username = rs.getString("username");
            String password = rs.getString("password");
            String email = rs.getString("email");
            System.out.println(id + " : " + username + " : " + password + " : " + email);
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        // 4. 釋放資源
        JDBCUtils.release(conn, stmt, rs);
    }
}

@Test
public void test2() {

    // 1. 載入驅動
    JDBCUtils.loadDriver();

    Connection conn = null;
    Statement stmt = null;

    try {
        // 2. 獲取連線
        conn = JDBCUtils.getConnection();
        // 3. 操作資料
        String sql = "update user set username='趙六', email='[email protected]' where id = 4;";
        stmt = conn.createStatement();
        int count = stmt.executeUpdate(sql);
        System.out.println("count = " + count);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        // 4. 釋放資源
        JDBCUtils.release(conn, stmt);
    }
}

工具類提高了程式碼的複用性問題,但是這個還能再進行優化

    // 屬性 (資料)
    private static final String driverClass = "com.mysql.cj.jdbc.Driver";
    private static final String url = "jdbc:mysql://localhost:3306/mydb?serverTimezone=UTC&characterEncoding=UTF-8";
    private static final String username = "root";
    private static final String password = "123456";

我們發現,是程式中的所有屬性都是固定的,一旦其中一個屬性發生變化,這個工具類就不能再用了,這種包裝方法叫硬編碼。我們可以考慮將屬性的賦值寫到配置檔案中去,當屬性改變的時候我們只需要更改配置檔案即可繼續使用這段程式碼,提高程式碼的通用性。這種叫軟編碼。 首先,建立配置檔案給工具類的屬性進行賦值

mydb.propertises

driverClass = com.mysql.cj.jdbc.Driver
url = jdbc:mysql://localhost:3306/day04?serverTimezone=UTC&characterEncoding=UTF-8
username = root
password = 123456

工具類程式碼實現:

靜態程式碼塊的特點 : 1. 類載入時, 自動執行靜態程式碼塊. 2. 靜態靜態塊僅會被執行一次, 因為類只會被虛擬機器載入一次.

public class JDBCUtils {
    // 屬性 (資料)
    // 靜態屬性如果使用 final 修飾, 還可以在 `靜態程式碼塊中` 實現賦值
    private static final String driverClass;
    private static final String url;
    private static final String username;
    private static final String password;

    // 靜態程式碼塊 :
    static {
        // 1. 建立一個 Properties 物件.
        Properties prop = new Properties();

        try {
            // 2. 載入配置檔案資料到 prop 物件中
            prop.load(new FileReader("jdbc.properties"));

            // 3. 如果載入成功, 為靜態屬性賦值
            driverClass = prop.getProperty("driverClass");
            url = prop.getProperty("url");
            username = prop.getProperty("username");
            password = prop.getProperty("password");

            // 載入驅動
            loadDriver();

        } catch (IOException e) {
            // 注意 : 配置檔案如果載入失敗, 直接丟擲一個執行時異常
            throw new RuntimeException("配置檔案載入失敗!");
        }
    }

    // 1. 載入驅動
    private static void loadDriver() {
        try {
            Class.forName(driverClass);
        } catch (ClassNotFoundException e) {
            // 說明 : 如果驅動載入失敗, 之後的所有操作就無需繼續執行了...
            throw new RuntimeException("驅動載入失敗!");
        }
    }

    // 2. 獲取連線
    public static Connection getConnection() throws SQLException {
        return DriverManager.getConnection(url, username, password);
    }

    // 3. 釋放資源
    public static void release(Connection conn, Statement stmt, ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            rs = null;  // clear to let GC do its work
        }

        // 呼叫下面的方法實現 conn, stmt
        release(conn, stmt);
    }

    public static void release(Connection conn, Statement stmt) {

        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            stmt = null;
        }

        if (conn != null) {
            try {
                conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
            conn = null;
        }
    }
}

測試類

@Test
public void test1() {

    Connection conn = null;
    Statement stmt = null;
    ResultSet rs = null;

    try {
        // 1. 獲取連線
        conn = JDBCUtils.getConnection();
        // 2. 操作資料
        String sql = "select * from user where id < 10;";
        stmt = conn.createStatement();
        rs = stmt.executeQuery(sql);
        while (rs.next()) {
            int id = rs.getInt("id");
            String username = rs.getString("username");
            String password = rs.getString("password");
            String email = rs.getString("email");
            System.out.println(id + " : " + username + " : " + password + " : " + email);
        }
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        // 3. 釋放資源
        JDBCUtils.release(conn, stmt, rs);
    }
}

@Test
public void test2() {

    Connection conn = null;
    Statement stmt = null;

    try {
        // 1. 獲取連線
        conn = JDBCUtils.getConnection();
        // 2. 操作資料
        String sql = "update user set username='趙六', email='[email protected]' where id = 4;";
        stmt = conn.createStatement();
        int count = stmt.executeUpdate(sql);
        System.out.println("count = " + count);
    } catch (SQLException e) {
        e.printStackTrace();
    } finally {
        // 3. 釋放資源
        JDBCUtils.release(conn, stmt);
    }
}