iT邦幫忙

2025 iThome 鐵人賽

DAY 22
0
自我挑戰組

Java 學生管理系統:打造可新增、刪除、修改、搜尋並保存資料的完整 CLI 應用系列 第 22

Day 22:看到.db檔的內容跟學 SQL CRUD 操作順便把 add / delete / update 改寫成 SQL

  • 分享至 

  • xImage
  •  

昨天設定完資料庫之後我發現我沒有辦法看到.db檔的內容因此今天第一件事是搞清楚what happened;

首先關於為什麼在我的finder裡看得到檔案卻,打開之後卻沒有內容?
因為 .db 是 二進位格式(binary file),它不是純文字(plain text),而是 SQLite 專用的內部結構。
therefore沒辦法隨便打開直接view。

而我的解決方法是在vscode裡裝extension;
https://ithelp.ithome.com.tw/upload/images/20251006/20178846wgx8MfC6eF.png

好進入正題:
SQL CRUD 操作與 Statement / PreparedStatement

第一:什麼是 SQL CRUD?
CRUD 是所有資料庫操作的四大基本功能:
C Create INSERT INTO 新增資料
R Read SELECT 查詢資料
U Update UPDATE 修改資料
D Delete DELETE FROM 刪除資料

二、JDBC 是怎麼讓 Java 執行 SQL 的?

JDBC(Java Database Connectivity)是 Java 官方提供的資料庫操作 API。
要讓 Java 跟 SQLite 對話,需要三個關鍵角色:
Connection 建立與資料庫的連線 DriverManager.getConnection(url)
Statement / PreparedStatement 傳送 SQL 指令給資料庫 conn.createStatement()
ResultSet 儲存 SQL 查詢的結果 stmt.executeQuery(sql)

三、Statement vs PreparedStatement
比較項 Statement PreparedStatement
SQL 寫法 直接把整句 SQL 寫成字串 使用 ? 當參數佔位符
安全性 ❌ 容易被 SQL injection 攻擊 ✅ 自動處理轉義、避免注入
效能 ❌ 每次都要重新解析 SQL ✅ 可預先編譯,提高效能
使用場合 小範圍、固定 SQL 真實專案、含使用者輸入

範例對比:
❌ 傳統 Statement(不安全)
Statement stmt = conn.createStatement();
stmt.executeUpdate("INSERT INTO students(name, age) VALUES('Tom', 18)");

如果使用者輸入:

name = "Tom'); DROP TABLE students; --"

那實際執行的 SQL 會變成:

INSERT INTO students(name, age) VALUES('Tom'); DROP TABLE students; --', 18);

結果會直接刪掉整個資料表
安全的 PreparedStatement
String sql = "INSERT INTO students(name, age) VALUES(?, ?)";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "Tom");
ps.setInt(2, 18);
ps.executeUpdate();

這樣 SQLite 會自動把輸入視為「文字內容」而不是程式碼。
安全、穩定,也比較快。

四、為什麼要新增 SqliteStudentRepository
1️⃣ StudentManager 的角色:
StudentManager 是邏輯層(Logic Layer),
它只決定「要做什麼」,但不管「怎麼做」。

它會呼叫 Repository 的方法:

repo.addStudent(new Student("Tom", 18));
repo.updateAge("Tom", 19);

2️⃣ SqliteStudentRepository 的角色:
這是資料層(Data Layer),
負責「跟資料庫打交道」,
也就是實際執行 SQL CRUD。

public void add(Student s) {
String sql = "INSERT INTO students(name, age) VALUES(?, ?)";
try (Connection conn = DriverManager.getConnection(url);
PreparedStatement ps = conn.prepareStatement(sql)) {
ps.setString(1, s.getName());
ps.setInt(2, s.getAge());
ps.executeUpdate();
} catch (SQLException e) {
System.out.println("新增失敗: " + e.getMessage());
}
}

那麼為什麼這樣設計?
分層清楚 StudentManager 負責邏輯,SqliteStudentRepository 負責資料庫
可維護性高 之後想改成 MySQL、CSV,只要換 Repository 不用改全部程式
安全性好 所有 SQL 都集中在一個地方管理
專業結構 這是業界常用的「DAO / Repository Pattern」設計方式

最後實作起來會長這樣:
https://ithelp.ithome.com.tw/upload/images/20251006/20178846iUF5GXm3za.png


上一篇
Day 21: SQLite
系列文
Java 學生管理系統:打造可新增、刪除、修改、搜尋並保存資料的完整 CLI 應用22
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言