news 2026/5/4 22:44:20

SpringBoot解析.mdb文件实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
SpringBoot解析.mdb文件实战指南

文章简介:本文介绍如何在SpringBoot项目中解析旧版Microsoft Access的.mdb文件。通过UCanAccess开源库,无需安装Access或ODBC驱动,即可实现跨平台数据读取。文中提供完整的Maven依赖配置、核心工具类封装及使用示例,帮助开发者快速完成遗留系统数据迁移。该方法尤其适合临时数据提取任务,为处理历史数据库提供便捷的Java解决方案。

最近在做一个数据迁移项目,需要从老旧的.mdb(Microsoft Access)文件中提取数据。虽然Access数据库现在用得不多,但在一些遗留系统中还能见到。网上查了一圈,发现UCanAccess这个神器,结合AI的帮助,很快就完成了需求开发。
以下是UCanAccess的文档地址http://ucanaccess.sourceforge.net/site.html

🚀 快速开始

1️⃣ 引入Maven依赖

首先,我们需要在pom.xml中添加UCanAccess的依赖:

<!-- 添加UCanAccess依赖 --><dependency><groupId>net.sf.ucanaccess</groupId><artifactId>ucanaccess</artifactId><version>5.0.1</version></dependency>

2️⃣ 核心工具类实现

下面是我封装的MdbJdbcUtil.java工具类,可以直接复制使用:

importjava.sql.*;importjava.util.*;importjava.util.stream.Collectors;importjava.util.stream.IntStream;publicclassMdbJdbcUtil{privatestaticfinalStringDRIVER_CLASS="net.ucanaccess.jdbc.UcanaccessDriver";privatestaticfinalStringURL_PREFIX="jdbc:ucanaccess://";privatestaticfinalStringURL_MEMORY=";memory=false";/** * 私有构造方法,防止实例化 */privateMdbJdbcUtil(){thrownewUnsupportedOperationException("This is a utility class and cannot be instantiated");}/** * 静态初始化块,加载数据库驱动 */static{try{Class.forName(DRIVER_CLASS);}catch(ClassNotFoundExceptione){thrownewRuntimeException("Failed to load UCanAccess JDBC driver",e);}}/** * 创建数据库连接 * * @param mdbPath MDB文件路径 * @return 数据库连接 * @throws SQLException 如果连接失败 */publicstaticConnectiongetConnection(StringmdbPath)throwsSQLException{if(mdbPath==null||mdbPath.trim().isEmpty()){thrownewIllegalArgumentException("MDB file path cannot be null or empty");}Propertiesprops=newProperties();props.put("charSet","UTF-8");StringdbUrl=URL_PREFIX+mdbPath+URL_MEMORY;returnDriverManager.getConnection(dbUrl,props);}/** * 执行带参数的查询并返回List<Map<String, Object>>结果 * * @param mdbPath MDB文件路径 * @param sql SQL查询语句 * @param params 查询参数列表 * @return 查询结果列表,每个Map代表一行数据 * @throws SQLException 如果查询失败 */publicstaticList<Map<String,Object>>queryForList(StringmdbPath,Stringsql,Object...params)throwsSQLException{validateParameters(mdbPath,sql);Connectionconn=null;PreparedStatementstmt=null;ResultSetrs=null;try{conn=getConnection(mdbPath);stmt=conn.prepareStatement(sql);// 设置查询参数if(params!=null){for(inti=0;i<params.length;i++){stmt.setObject(i+1,params[i]);}}rs=stmt.executeQuery();returnconvertResultSetToList(rs);}finally{closeResources(rs,stmt,conn);}}/** * 验证参数有效性 * * @param mdbPath MDB文件路径 * @param sql SQL语句 */privatestaticvoidvalidateParameters(StringmdbPath,Stringsql){if(mdbPath==null||mdbPath.trim().isEmpty()){thrownewIllegalArgumentException("MDB file path cannot be null or empty");}if(sql==null||sql.trim().isEmpty()){thrownewIllegalArgumentException("SQL statement cannot be null or empty");}}/** * 关闭数据库资源 * * @param rs ResultSet对象 * @param stmt Statement对象 * @param conn Connection对象 */privatestaticvoidcloseResources(ResultSetrs,Statementstmt,Connectionconn){try{if(rs!=null){rs.close();}}catch(SQLExceptione){// 记录日志但不抛出异常System.err.println("Failed to close ResultSet: "+e.getMessage());}try{if(stmt!=null){stmt.close();}}catch(SQLExceptione){System.err.println("Failed to close Statement: "+e.getMessage());}try{if(conn!=null){conn.close();}}catch(SQLExceptione){System.err.println("Failed to close Connection: "+e.getMessage());}}/** * 将ResultSet转换为List<Map<String, Object>> * * @param rs ResultSet对象 * @return 转换后的列表 * @throws SQLException 如果转换失败 */privatestaticList<Map<String,Object>>convertResultSetToList(ResultSetrs)throwsSQLException{List<Map<String,Object>>resultList=newArrayList<>();if(rs==null){returnresultList;}ResultSetMetaDatametaData=rs.getMetaData();intcolumnCount=metaData.getColumnCount();// 获取列名列表List<String>columnNames=IntStream.rangeClosed(1,columnCount).mapToObj(i->{try{returnmetaData.getColumnLabel(i);}catch(SQLExceptione){thrownewRuntimeException("Failed to get column name",e);}}).collect(Collectors.toList());// 遍历结果集while(rs.next()){Map<String,Object>row=newLinkedHashMap<>();for(StringcolumnName:columnNames){row.put(columnName,rs.getObject(columnName));}resultList.add(row);}returnresultList;}}

3️⃣ 如何使用工具类

publicclassExample{publicstaticvoidmain(String[]args)throwsSQLException{Stringsql="select * from UserInfo";StringmdbPath="D:\\mdb\\mdbtest.mdb";List<Map<String,Object>>resultList=MdbJdbcUtil.queryForList(mdbPath,sql);System.out.println("查询结果数量"+resultList.size());for(Map<String,Object>row:resultList){System.out.println(row);}}}

运行上面的代码,你会看到如下输出:

查询结果数量: 2 {UserNO=1, UserID=Admin, UserName=管理员Admin, UserPassword=123456} {UserNO=2, UserID=Xiuji, UserName=管理员Xiuji, UserPassword=123456789}

⚠️ 注意事项

  • memory设置

在处理大型数据库并使用默认的"memory"设置(即驱动属性memory=true)时,建议用户通过-Xms和-Xmx选项为JVM分配足够的内存。否则,必须将驱动的"memory"属性设置为"false"

  • ignoreCase设置

ignoreCase:此属性用于禁用(ignoreCase=true)或启用(ignoreCase=false)文本比较的区分大小写功能。默认值=true。

📝 总结

通过UCanAccess库,我们可以轻松地在SpringBoot项目中解析.mdb文件,无需依赖Windows环境或ODBC驱动。这个方案特别适合:

  • ✅ 临时数据提取任务
  • ✅ 遗留系统数据迁移
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/27 5:16:32

Kook Zimage真实幻想Turbo部署案例:AIGC培训课程幻想风格实训模块

Kook Zimage真实幻想Turbo部署案例&#xff1a;AIGC培训课程幻想风格实训模块 1. 为什么这个模型特别适合AIGC教学实训&#xff1f; 在AIGC培训课程中&#xff0c;学员最常遇到的卡点不是“不会写提示词”&#xff0c;而是“写了却出不来想要的效果”——尤其是幻想类题材&am…

作者头像 李华
网站建设 2026/4/28 6:46:12

5个mPLUG视觉问答的创意应用场景解析

5个mPLUG视觉问答的创意应用场景解析 本文聚焦于本地化部署的&#x1f441; mPLUG 视觉问答智能分析工具&#xff0c;深入解析其在真实业务场景中的5个高价值、可落地的应用方向。不同于泛泛而谈的技术介绍&#xff0c;本文所有案例均基于该镜像的实际能力边界——全本地运行、…

作者头像 李华
网站建设 2026/4/27 7:58:41

5步搞定:TranslateGemma本地化部署与使用全攻略

5步搞定&#xff1a;TranslateGemma本地化部署与使用全攻略 1. 为什么你需要本地化的TranslateGemma 你是否遇到过这些翻译场景&#xff1a; 正在审阅一份英文技术白皮书&#xff0c;但在线翻译工具频繁中断、响应慢&#xff0c;还可能把“bias”译成“偏见”而非“偏差”&a…

作者头像 李华
网站建设 2026/4/20 16:18:34

FLUX.1-dev应用案例:打造自动化内容生产流水线

FLUX.1-dev应用案例&#xff1a;打造自动化内容生产流水线 你是否曾盯着一张刚生成的营销图发呆——构图不错&#xff0c;但产品位置偏左&#xff1b;色彩很潮&#xff0c;可品牌Slogan字体太小&#xff1b;风格统一&#xff0c;偏偏背景里混进了一个模糊的竞品Logo&#xff1…

作者头像 李华