| 方案 | 原理 | 優點 | 缺點 | 現狀 |
|---|---|---|---|---|
| JDBC-ODBC Bridge | JDK 內建橋接器 → Windows ODBC 驅動 → Access | 無需額外 JAR、JDK 7 內建 | 需機器配置 DSN、僅 Windows、32/64 位匹配問題、JDK 8 移除 | 已廢棄 (JDK 8 移除) |
| UCanAccess | 純 Java 驅動 (基於 Jackcess/HSQLDB) | 跨平台、無需 ODBC/Access 安裝、支援 .mdb/.accdb、Maven 管理 | 效能較原生略低、大檔案記憶體佔用高 | 推薦方案 (活躍維護) |
| Jackcess | 底層純 Java Access 檔案讀寫庫 | 無 JDBC 開銷、直接操作檔案 | 非標準 JDBC API、功能較少 | 底層庫,UCanAccess 依賴它 |
<dependency>
<groupId>net.sf.ucanaccess</groupId>
<artifactId>ucanaccess</artifactId>
<version>5.0.1</version> <!-- 檢查最新版 -->
</dependency>
傳遞依賴包含:jackcess、hsqldb、commons-lang3、commons-logging。
import java.sql.*;
public class UCanAccessDemo {
public static void main(String[] args) {
// 檔案路徑:.mdb (Access 2003) 或 .accdb (Access 2007+)
String filePath = "C:/data/mydb.accdb";
String url = "jdbc:ucanaccess://" + filePath; // 絕對路徑
// 相對路徑(相對於 working directory)
// String url = "jdbc:ucanaccess://./data/mydb.accdb";
// 僅讀模式(避免鎖定檔案)
// String url = "jdbc:ucanaccess://" + filePath + ";readonly=true";
try (Connection conn = DriverManager.getConnection(url)) {
System.out.println("連線成功!");
// 查詢範例
String sql = "SELECT id, name, email FROM users WHERE active = true";
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
while (rs.next()) {
System.out.printf("ID:%d, Name:%s, Email:%s%n",
rs.getInt("id"), rs.getString("name"), rs.getString("email"));
}
}
// 參數化查詢(防注入)
String paramSql = "SELECT * FROM orders WHERE customer_id = ? AND order_date > ?";
try (PreparedStatement ps = conn.prepareStatement(paramSql)) {
ps.setInt(1, 1001);
ps.setDate(2, java.sql.Date.valueOf("2024-01-01"));
try (ResultSet rs = ps.executeQuery()) {
// 處理結果
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
// 僅供參考,現代專案勿使用
String url = "jdbc:odbc:Driver={Microsoft Access Driver (*.mdb)};DBQ=C:/data/mydb.mdb";
// 或使用系統 DSN
// String url = "jdbc:odbc:MyAccessDSN";
try {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); // JDK 內建
Connection conn = DriverManager.getConnection(url, "username", "password");
// ...
} catch (Exception e) {
e.printStackTrace();
}
// HikariCP 配置範例
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:ucanaccess://C:/data/mydb.accdb");
config.setDriverClassName("net.ucanaccess.jdbc.UcanaccessDriver");
config.setMaximumPoolSize(5); // Access 並發能力有限,建議小池
config.setConnectionTimeout(30000);
HikariDataSource ds = new HikariDataSource(config);
jdbc:ucanaccess://path?memory=false:關閉記憶體資料庫鎮像,直接讀寫檔案(減少記憶體,降低速度)。jdbc:ucanaccess://path?opencursor=true:保持游標開啟,適合大量讀取。CHECKPOINT 或 BACKUP 壓縮資料庫檔案。| 錯誤 | 原因 | 解決 |
|---|---|---|
| No suitable driver | 驅動類未載入、Maven 依賴缺失 | 檢查 ucanaccess JAR、DriverManager.getConnection 自動載入 (JDBC 4.0+) |
| File locked / Permission denied | Access 檔案被其他程式獨佔、唯讀屬性 | 關閉 Access 應用程式、檔案屬性移除唯讀、或用 readonly=true |
| OutOfMemoryError | 大資料庫載入記憶體 | 加 memory=false、增加 JVM -Xmx、分批處理 |
| Unsupported operation | Access SQL 語法差異 | 使用 Access 相容 SQL、避免複雜 JOIN/子查詢 |
Access 適合單機小型應用,企業級系統建議遷移至:
遷移策略:UCanAccess 導出 SQL → 目標資料庫匯入 → 修正語法差異 → 切換連線池配置。