JavaSE基礎知識分享(十一)

ikestu小猪發表於2024-08-20

寫在前面

今天繼續講Java連線MySQL資料庫和Java中的物件流(序列化與反序列化)的知識!

Java 與 MySQL 連線

要使用 Java 操作 MySQL 資料庫,我們需要透過 JDBC(Java Database Connectivity)進行連線。JDK 本身不提供對具體資料庫的操作能力,因此需要使用資料庫提供的驅動包來實現。

JDBC 程式設計 6 步

  1. 註冊驅動
    告訴 Java 程式即將連線的資料庫型別。

    Class.forName("com.mysql.cj.jdbc.Driver");
    
  2. 獲取連線
    開啟 JVM 程序和資料庫程序之間的通道。

    Connection conn = DriverManager.getConnection(
        "jdbc:mysql://主機的IP地址:3306/資料庫名?useUnicode=true&characterEncoding=utf-8&useSSL=false",
        "root", "123456");
    
  3. 獲取資料庫操作物件
    建立用於執行 SQL 語句的物件。

    Statement state = conn.createStatement();
    

    注意:進行查詢操作時,推薦使用 PreparedStatement,以防止 SQL 注入。

    PreparedStatement ps = conn.prepareStatement(
        "UPDATE user SET password=? WHERE username=?");
    
  4. 執行 SQL 語句

    • executeQuery: 用於查詢(DQL)。
    • executeUpdate: 用於增刪改(DML)。
    // 執行查詢
    ResultSet resultSet = state.executeQuery("SELECT * FROM tableName");
    
    // 執行更新
    int rowsAffected = state.executeUpdate("UPDATE tableName SET column=value WHERE condition");
    
  5. 處理查詢結果集

    • 僅在執行查詢語句(SELECT)時需要處理。
    while (resultSet.next()) {
        // 獲取每列的值
        int eno = resultSet.getInt("eno");
    }
    
  6. 釋放資源
    使用完資源後關閉連線。

    state.close();
    conn.close();
    

MySQL Connector/J 版本對比

  • MySQL Connector/J 5.1

    • 支援 Java 5 及以上版本。
    • 支援 MySQL 5.6、5.7 和 8.0。
    • 支援 JDBC 3.0、4.0、4.1 和 4.2。
    • Driver 實現類:com.mysql.jdbc.Driver.
  • MySQL Connector/J 8.0

    • 支援 Java 8 及以上版本。
    • 支援 MySQL 5.6、5.7 和 8.0。
    • 支援 JDBC 4.2。
    • Driver 實現類:com.mysql.cj.jdbc.Driver.

Properties 集合

Properties 類用於封裝和管理與 MySQL 連線相關的引數配置。

Properties 概述

Properties 類是 Map 集合的一個特殊實現,主要用於處理鍵值對形式的配置資料。它提供了對配置檔案的讀取和寫入功能。

Properties 的特殊功能

  • 設定屬性

    public Object setProperty(String key, String value);
    

    用於將指定的鍵值對新增到 Properties 集合中。

  • 獲取屬性

    public String getProperty(String key);
    

    根據鍵獲取對應的值。

  • 獲取所有鍵名

    public Set<String> stringPropertyNames();
    

    獲取所有的鍵名集合。

Properties 和 IO 流的結合使用

  • 載入屬性

    public void load(Reader reader);
    

    從指定的 Reader 中讀取屬性列表(鍵值對)。

  • 儲存屬性

    public void store(Writer writer, String comments);
    

    將屬性列表(鍵值對)寫入到指定的 Writer 中,帶有註釋。

使用示例

  1. 建立 Properties 類物件

    Properties properties = new Properties();
    
  2. 指定要讀取的配置檔案

    properties.load(new BufferedReader(new FileReader("路徑/info.properties")));
    
  3. 獲取配置項

    String url = properties.getProperty("url");
    String username = properties.getProperty("user");
    String password = properties.getProperty("password");
    
  4. 使用獲取的引數建立資料庫連線

    Connection conn = MysqlTool.getConnection(url, username, password);
    System.out.println("成功獲取與資料庫的連結物件:" + conn);
    

示例配置檔案 (info.properties)

password=123456
user=root
url=jdbc:mysql://主機的IP地址:3306/具體資料庫名?useUnicode=true&characterEncoding=utf-8&useSSL=false

序列化與反序列化

序列化流

  • 序列化:將物件轉換為可以透過網路傳輸的位元組流。

    • 物件輸出流:ObjectOutputStream
  • 反序列化:將位元組流還原為物件。

    • 物件輸入流:ObjectInputStream

注:只有實現Serializable介面的物件才能進行序列化,這個和實現克隆是一樣的,相當於給類加一個標記!

示例程式碼

讀取物件

ObjectInputStream ois = new ObjectInputStream(new FileInputStream("和輸出檔案路徑一樣的路徑,編碼不一樣也會出現不能反序列化"));
Object o = ois.readObject(); // 例如 new Student("魏一民", 18);
Student student = (Student) o;
System.out.println(student);

寫入物件

ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("輸入檔案路徑"));
Student s1 = new Student("魏一民", 18, "安徽合肥", "110");
oos.writeObject(s1);
oos.flush(); // 確保資料寫入檔案

序列化操作問題

  • 為什麼要實現序列化?

    • 持久化:將物件狀態儲存到磁碟或資料庫中,以便後續恢復。
    • 通訊:在網路中將物件透過位元組流傳送到遠端計算機。
    • 深度複製:透過序列化和反序列化實現物件的深度複製。
  • 如何實現序列化?

    • 類必須實現 java.io.Serializable 介面。這個介面是一個標記介面,沒有方法需要實現。
    import java.io.Serializable;
    
    public class MyClass implements Serializable {
        private static final long serialVersionUID = 1L; // 推薦使用
    
        private String name;
        private int age;
    
        // Getter 和 Setter 方法
    }
    
    • serialVersionUID:用於版本控制,確保序列化和反序列化時的類版本一致。
  • 使用 transient 關鍵字宣告不需要序列化的成員變數

    import java.io.Serializable;
    
    public class MyClass implements Serializable {
        private static final long serialVersionUID = 1L;
    
        private String name;
        private transient int age; // 不會被序列化
    
        // Getter 和 Setter 方法
    }
    
  • 序列化資料後,再次修改類檔案,如何解決問題?

    • 版本控制:使用 serialVersionUID 來控制版本匹配,確保序列化和反序列化的類版本一致。
    • 自定義 readObjectwriteObject 方法:處理類的版本變化。
    • transient 關鍵字:標記不需要序列化的欄位,避免因欄位缺失導致問題。

相關文章