寫在前面
今天繼續講Java連線MySQL資料庫和Java中的物件流(序列化與反序列化)的知識!
Java 與 MySQL 連線
要使用 Java 操作 MySQL 資料庫,我們需要透過 JDBC(Java Database Connectivity)進行連線。JDK 本身不提供對具體資料庫的操作能力,因此需要使用資料庫提供的驅動包來實現。
JDBC 程式設計 6 步
-
註冊驅動:
告訴 Java 程式即將連線的資料庫型別。Class.forName("com.mysql.cj.jdbc.Driver");
-
獲取連線:
開啟 JVM 程序和資料庫程序之間的通道。Connection conn = DriverManager.getConnection( "jdbc:mysql://主機的IP地址:3306/資料庫名?useUnicode=true&characterEncoding=utf-8&useSSL=false", "root", "123456");
-
獲取資料庫操作物件:
建立用於執行 SQL 語句的物件。Statement state = conn.createStatement();
注意:進行查詢操作時,推薦使用
PreparedStatement
,以防止 SQL 注入。PreparedStatement ps = conn.prepareStatement( "UPDATE user SET password=? WHERE username=?");
-
執行 SQL 語句:
executeQuery
: 用於查詢(DQL)。executeUpdate
: 用於增刪改(DML)。
// 執行查詢 ResultSet resultSet = state.executeQuery("SELECT * FROM tableName"); // 執行更新 int rowsAffected = state.executeUpdate("UPDATE tableName SET column=value WHERE condition");
-
處理查詢結果集:
- 僅在執行查詢語句(SELECT)時需要處理。
while (resultSet.next()) { // 獲取每列的值 int eno = resultSet.getInt("eno"); }
-
釋放資源:
使用完資源後關閉連線。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
中,帶有註釋。
使用示例
-
建立
Properties
類物件:Properties properties = new Properties();
-
指定要讀取的配置檔案:
properties.load(new BufferedReader(new FileReader("路徑/info.properties")));
-
獲取配置項:
String url = properties.getProperty("url"); String username = properties.getProperty("user"); String password = properties.getProperty("password");
-
使用獲取的引數建立資料庫連線:
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
來控制版本匹配,確保序列化和反序列化的類版本一致。 - 自定義
readObject
和writeObject
方法:處理類的版本變化。 - transient 關鍵字:標記不需要序列化的欄位,避免因欄位缺失導致問題。
- 版本控制:使用