設計目標
- 封裝連線建立、查詢執行、結果集轉換(Vector/TableModel)。
- 支援 Swing
JTable 直接綁定 DefaultTableModel。
- 集中管理連線字串與驅動載入。
核心類別:DbConnection
import java.sql.*;
import java.util.Vector;
import javax.swing.table.*;
public class DbConnection {
private Connection conn;
private final String URL = "jdbc:sqlserver://localhost:1433;DatabaseName=Permission";
private final String USER = "sa";
private final String PWD = "770417";
/** 取得/建立連線 */
public Connection getConn() {
if (conn != null) return conn;
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
conn = DriverManager.getConnection(URL, USER, PWD);
} catch (ClassNotFoundException | SQLException e) {
e.printStackTrace();
conn = null;
}
return conn;
}
/** 執行查詢回傳 ResultSet(呼叫端需自行關閉) */
public ResultSet getRs(String sql) {
try {
if (conn == null) getConn();
Statement stmt = conn.createStatement();
return stmt.executeQuery(sql);
} catch (SQLException e) {
e.printStackTrace();
return null;
}
}
/** 查詢單欄位結果集 → Vector<String> */
public Vector<String> getVector(String sql) {
Vector<String> v = new Vector<>();
try (ResultSet rs = getRs(sql)) {
if (rs != null) while (rs.next()) v.add(rs.getString(1));
} catch (SQLException e) { e.printStackTrace(); }
return v;
}
/** 取得欄位名稱 → Vector<String>(表頭) */
public Vector<String> getTableTitle(String sql) {
Vector<String> title = new Vector<>();
try (ResultSet rs = getRs(sql)) {
if (rs != null) {
ResultSetMetaData md = rs.getMetaData();
for (int i = 1; i <= md.getColumnCount(); i++)
title.add(md.getColumnName(i));
}
} catch (SQLException e) { e.printStackTrace(); }
return title;
}
/** 取得完整資料 → Vector<Vector<String>>(表身) */
public Vector<Vector<String>> getTableContent(String sql) {
Vector<Vector<String>> content = new Vector<>();
try (ResultSet rs = getRs(sql)) {
if (rs != null) {
ResultSetMetaData md = rs.getMetaData();
int cols = md.getColumnCount();
while (rs.next()) {
Vector<String> row = new Vector<>();
for (int i = 1; i <= cols; i++) row.add(rs.getString(i));
content.add(row);
}
}
} catch (SQLException e) { e.printStackTrace(); }
return content;
}
/** 一鍵產生 TableModel 供 JTable 使用 */
public TableModel getTableModel(String sql) {
return new DefaultTableModel(getTableContent(sql), getTableTitle(sql));
}
/** 測試主程式 */
public static void main(String[] args) {
DbConnection db = new DbConnection();
Vector<Vector<String>> data = db.getTableContent("SELECT * FROM [user]");
for (Vector<String> row : data) {
for (String col : row) System.out.print(col + "\t");
System.out.println();
}
}
}
使用情境
// Swing 介面中
JTable table = new JTable();
table.setModel(db.getTableModel("SELECT userId, userName, passWord FROM [user]"));
// 自動顯示表頭與資料,支援排序、選取等標準功能
改進建議(生產級)
- 連線池:移除單例
Connection,改用 DataSource 取得連線並即用即還。
- PreparedStatement:所有查詢改用參數化 SQL,防止注入並利用執行計畫快取。
- 泛型化:回傳
List<Map<String, Object>> 或自定義 DTO,避免 Vector 過時且非型別安全。
- 資源管理:全面採用 try-with-resources 確保
ResultSet/Statement/Connection 關閉。
- 異常處理:拋出自定義
DataAccessException 而非吞噬或回傳 null。
對照表:Vector vs 現代集合
| 特性 | Vector | ArrayList / List<Map> |
| 執行緒安全 | 同步化(效能較差) | 非同步(需外部同步或用 CopyOnWriteArrayList) |
| 型別安全 | 無(原始類型) | 泛型支援 |
| Swing 相容 | DefaultTableModel 直接接受 | 需轉換或自訂 TableModel |
教學/原型階段用 Vector 快速對接 Swing 可接受;正式專案建議換用 List<Map> + 自訂 AbstractTableModel。