SpringBoot實(shí)現(xiàn)解析.mdb文件的實(shí)戰(zhàn)指南
最近在做一個數(shù)據(jù)遷移項(xiàng)目,需要從老舊的.mdb(Microsoft Access)文件中提取數(shù)據(jù)。雖然Access數(shù)據(jù)庫現(xiàn)在用得不多,但在一些遺留系統(tǒng)中還能見到。網(wǎng)上查了一圈,發(fā)現(xiàn)UCanAccess這個神器,結(jié)合AI的幫助,很快就完成了需求開發(fā)。
以下是UCanAccess的文檔地址ucanaccess.sourceforge.net/site.html
引入Maven依賴
首先,我們需要在pom.xml中添加UCanAccess的依賴:
<!-- 添加UCanAccess依賴 -->
<dependency>
<groupId>net.sf.ucanaccess</groupId>
<artifactId>ucanaccess</artifactId>
<version>5.0.1</version>
</dependency>
核心工具類實(shí)現(xiàn)
下面是我封裝的MdbJdbcUtil.java工具類,可以直接復(fù)制使用:
import java.sql.*;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class MdbJdbcUtil {
private static final String DRIVER_CLASS = "net.ucanaccess.jdbc.UcanaccessDriver";
private static final String URL_PREFIX = "jdbc:ucanaccess://";
private static final String URL_MEMORY = ";memory=false";
/**
* 私有構(gòu)造方法,防止實(shí)例化
*/
private MdbJdbcUtil() {
throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
}
/**
* 靜態(tài)初始化塊,加載數(shù)據(jù)庫驅(qū)動
*/
static {
try {
Class.forName(DRIVER_CLASS);
} catch (ClassNotFoundException e) {
throw new RuntimeException("Failed to load UCanAccess JDBC driver", e);
}
}
/**
* 創(chuàng)建數(shù)據(jù)庫連接
*
* @param mdbPath MDB文件路徑
* @return 數(shù)據(jù)庫連接
* @throws SQLException 如果連接失敗
*/
public static Connection getConnection(String mdbPath) throws SQLException {
if (mdbPath == null || mdbPath.trim().isEmpty()) {
throw new IllegalArgumentException("MDB file path cannot be null or empty");
}
Properties props = new Properties();
props.put("charSet", "UTF-8");
String dbUrl = URL_PREFIX + mdbPath + URL_MEMORY;
return DriverManager.getConnection(dbUrl, props);
}
/**
* 執(zhí)行帶參數(shù)的查詢并返回List<Map<String, Object>>結(jié)果
*
* @param mdbPath MDB文件路徑
* @param sql SQL查詢語句
* @param params 查詢參數(shù)列表
* @return 查詢結(jié)果列表,每個Map代表一行數(shù)據(jù)
* @throws SQLException 如果查詢失敗
*/
public static List<Map<String, Object>> queryForList(String mdbPath, String sql, Object... params) throws SQLException {
validateParameters(mdbPath, sql);
Connection conn = null;
PreparedStatement stmt = null;
ResultSet rs = null;
try {
conn = getConnection(mdbPath);
stmt = conn.prepareStatement(sql);
// 設(shè)置查詢參數(shù)
if (params != null) {
for (int i = 0; i < params.length; i++) {
stmt.setObject(i + 1, params[i]);
}
}
rs = stmt.executeQuery();
return convertResultSetToList(rs);
} finally {
closeResources(rs, stmt, conn);
}
}
/**
* 驗(yàn)證參數(shù)有效性
*
* @param mdbPath MDB文件路徑
* @param sql SQL語句
*/
private static void validateParameters(String mdbPath, String sql) {
if (mdbPath == null || mdbPath.trim().isEmpty()) {
throw new IllegalArgumentException("MDB file path cannot be null or empty");
}
if (sql == null || sql.trim().isEmpty()) {
throw new IllegalArgumentException("SQL statement cannot be null or empty");
}
}
/**
* 關(guān)閉數(shù)據(jù)庫資源
*
* @param rs ResultSet對象
* @param stmt Statement對象
* @param conn Connection對象
*/
private static void closeResources(ResultSet rs, Statement stmt, Connection conn) {
try {
if (rs != null) {
rs.close();
}
} catch (SQLException e) {
// 記錄日志但不拋出異常
System.err.println("Failed to close ResultSet: " + e.getMessage());
}
try {
if (stmt != null) {
stmt.close();
}
} catch (SQLException e) {
System.err.println("Failed to close Statement: " + e.getMessage());
}
try {
if (conn != null) {
conn.close();
}
} catch (SQLException e) {
System.err.println("Failed to close Connection: " + e.getMessage());
}
}
/**
* 將ResultSet轉(zhuǎn)換為List<Map<String, Object>>
*
* @param rs ResultSet對象
* @return 轉(zhuǎn)換后的列表
* @throws SQLException 如果轉(zhuǎn)換失敗
*/
private static List<Map<String, Object>> convertResultSetToList(ResultSet rs) throws SQLException {
List<Map<String, Object>> resultList = new ArrayList<>();
if (rs == null) {
return resultList;
}
ResultSetMetaData metaData = rs.getMetaData();
int columnCount = metaData.getColumnCount();
// 獲取列名列表
List<String> columnNames = IntStream.rangeClosed(1, columnCount)
.mapToObj(i -> {
try {
return metaData.getColumnLabel(i);
} catch (SQLException e) {
throw new RuntimeException("Failed to get column name", e);
}
})
.collect(Collectors.toList());
// 遍歷結(jié)果集
while (rs.next()) {
Map<String, Object> row = new LinkedHashMap<>();
for (String columnName : columnNames) {
row.put(columnName, rs.getObject(columnName));
}
resultList.add(row);
}
return resultList;
}
}
如何使用工具類
public class Example {
public static void main(String[] args) throws SQLException {
String sql = "select * from UserInfo";
String mdbPath = "D:\mdb\mdbtest.mdb";
List<Map<String, Object>> resultList = MdbJdbcUtil.queryForList(mdbPath,sql);
System.out.println("查詢結(jié)果數(shù)量"+resultList.size());
for (Map<String, Object> row : resultList) {
System.out.println(row);
}
}
}
運(yùn)行上面的代碼,你會看到如下輸出:
查詢結(jié)果數(shù)量: 2
{UserNO=1, UserID=Admin, UserName=管理員Admin, UserPassword=123456}
{UserNO=2, UserID=Xiuji, UserName=管理員Xiuji, UserPassword=123456789}
注意事項(xiàng)
1.memory設(shè)置
在處理大型數(shù)據(jù)庫并使用默認(rèn)的"memory"設(shè)置(即驅(qū)動屬性memory=true)時,建議用戶通過-Xms和-Xmx選項(xiàng)為JVM分配足夠的內(nèi)存。否則,必須將驅(qū)動的"memory"屬性設(shè)置為"false"

2.ignoreCase設(shè)置
ignoreCase:此屬性用于禁用(ignoreCase=true)或啟用(ignoreCase=false)文本比較的區(qū)分大小寫功能。默認(rèn)值=true。

總結(jié)
通過UCanAccess庫,我們可以輕松地在SpringBoot項(xiàng)目中解析.mdb文件,無需依賴Windows環(huán)境或ODBC驅(qū)動。這個方案特別適合:
- 臨時數(shù)據(jù)提取任務(wù)
- 遺留系統(tǒng)數(shù)據(jù)遷移
到此這篇關(guān)于SpringBoot實(shí)現(xiàn)解析.mdb文件的實(shí)戰(zhàn)指南的文章就介紹到這了,更多相關(guān)SpringBoot解析mdb文件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java猜數(shù)字小游戲?qū)崿F(xiàn)辦法與詳解
Java猜數(shù)字游戲是一款簡單的命令行游戲,玩家需要在1到100之間猜測一個由計(jì)算機(jī)隨機(jī)生成的數(shù)字,這篇文章主要介紹了Java猜數(shù)字小游戲?qū)崿F(xiàn)辦法與詳解的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-11-11
SpringBoot整合Spring?Data?JPA的詳細(xì)方法
JPA全稱為Java Persistence API(Java持久層API),是一個基于ORM的標(biāo)準(zhǔn)規(guī)范,在這個規(guī)范中,JPA只定義標(biāo)準(zhǔn)規(guī)則,不提供實(shí)現(xiàn),本文重點(diǎn)給大家介紹SpringBoot整合Spring?Data?JPA的相關(guān)知識,感興趣的朋友一起看看吧2022-02-02
Hadoop運(yùn)行時遇到j(luò)ava.io.FileNotFoundException錯誤的解決方法
今天給大家?guī)淼氖顷P(guān)于Java的相關(guān)知識,文章圍繞著Hadoop運(yùn)行時遇到j(luò)ava.io.FileNotFoundException錯誤展開,文中有非常詳細(xì)的解決方法,需要的朋友可以參考下2021-06-06
Mybatis-plus通用查詢方法封裝的實(shí)現(xiàn)
本文主要介紹了Mybatis-plus通用查詢方法封裝的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07
基于springboot創(chuàng)建mybatis的完整步驟
MyBatis是一款優(yōu)秀的數(shù)據(jù)庫持久層框架,相比Hibernate我更喜歡使用MyBatis,看的到SQL還是讓人更安心點(diǎn),這篇文章主要給大家介紹了關(guān)于基于springboot創(chuàng)建mybatis的完整步驟,需要的朋友可以參考下2024-03-03

