SpringBoot实现解析.mdb文件的实战指南

 更新时间:2026年02月04日 08:33:17   作者:修己xj  
这篇文章主要为大家详细介绍了如何在SpringBoot项目中解析旧版Microsoft Access的.mdb文件,文中提供完整的Maven依赖配置、核心工具类封装及使用示例,帮助开发者快速完成遗留系统数据迁移,希望对大家有所帮助

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

以下是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>

核心工具类实现

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

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";

    /**
     * 私有构造方法,防止实例化
     */
    private MdbJdbcUtil() {
        throw new UnsupportedOperationException("This is a utility class and cannot be instantiated");
    }
    /**
     * 静态初始化块,加载数据库驱动
     */
    static {
        try {
            Class.forName(DRIVER_CLASS);
        } catch (ClassNotFoundException e) {
            throw new RuntimeException("Failed to load UCanAccess JDBC driver", e);
        }
    }

    /**
     * 创建数据库连接
     *
     * @param mdbPath MDB文件路径
     * @return 数据库连接
     * @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);
    }
    /**
     * 执行带参数的查询并返回List<Map<String, Object>>结果
     *
     * @param mdbPath MDB文件路径
     * @param sql SQL查询语句
     * @param params 查询参数列表
     * @return 查询结果列表,每个Map代表一行数据
     * @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);

            // 设置查询参数
            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);
        }
    }

    /**
     * 验证参数有效性
     *
     * @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");
        }
    }

    /**
     * 关闭数据库资源
     *
     * @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转换为List<Map<String, Object>>
     *
     * @param rs ResultSet对象
     * @return 转换后的列表
     * @throws SQLException 如果转换失败
     */
    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());

        // 遍历结果集
        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("查询结果数量"+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}

注意事项

1.memory设置

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

2.ignoreCase设置

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

总结

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

  • 临时数据提取任务
  • 遗留系统数据迁移

到此这篇关于SpringBoot实现解析.mdb文件的实战指南的文章就介绍到这了,更多相关SpringBoot解析mdb文件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java猜数字小游戏实现办法与详解

    Java猜数字小游戏实现办法与详解

    Java猜数字游戏是一款简单的命令行游戏,玩家需要在1到100之间猜测一个由计算机随机生成的数字,这篇文章主要介绍了Java猜数字小游戏实现办法与详解的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-11-11
  • SpringBoot整合Spring Data JPA的详细方法

    SpringBoot整合Spring Data JPA的详细方法

    JPA全称为Java Persistence API(Java持久层API),是一个基于ORM的标准规范,在这个规范中,JPA只定义标准规则,不提供实现,本文重点给大家介绍SpringBoot整合Spring Data JPA的相关知识,感兴趣的朋友一起看看吧
    2022-02-02
  • Hadoop运行时遇到java.io.FileNotFoundException错误的解决方法

    Hadoop运行时遇到java.io.FileNotFoundException错误的解决方法

    今天给大家带来的是关于Java的相关知识,文章围绕着Hadoop运行时遇到java.io.FileNotFoundException错误展开,文中有非常详细的解决方法,需要的朋友可以参考下
    2021-06-06
  • 使用Java编写一个文件批量重命名工具

    使用Java编写一个文件批量重命名工具

    这篇文章主要为大家详细介绍了如何使用Java编写一个文件批量重命名工具,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-12-12
  • Mybatis-plus通用查询方法封装的实现

    Mybatis-plus通用查询方法封装的实现

    本文主要介绍了Mybatis-plus通用查询方法封装的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • 基于springboot创建mybatis的完整步骤

    基于springboot创建mybatis的完整步骤

    MyBatis是一款优秀的数据库持久层框架,相比Hibernate我更喜欢使用MyBatis,看的到SQL还是让人更安心点,这篇文章主要给大家介绍了关于基于springboot创建mybatis的完整步骤,需要的朋友可以参考下
    2024-03-03
  • Java经典算法之快速排序详解

    Java经典算法之快速排序详解

    这篇文章主要给大家介绍了关于Java经典算法之快速排序的相关资料,需快速排序是一种分治法的排序算法,其基本思想是通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有元素均比另一部分的元素小,然后分别对这两部分继续进行排序,需要的朋友可以参考下
    2024-07-07
  • java单例模式实现面板切换

    java单例模式实现面板切换

    这篇文章主要为大家详细介绍了java单例模式实现面板切换,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-11-11
  • Java程序包不存在的3种解决方法总结

    Java程序包不存在的3种解决方法总结

    包存在的,但是启动项目的时候提示包不存在,所以解决下,这篇文章主要给大家介绍了关于Java程序包不存在的3种解决方法,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2023-01-01
  • 详解SpringBoot如何开启异步编程

    详解SpringBoot如何开启异步编程

    本文主要介绍了详解SpringBoot如何开启异步编程,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-04-04

最新评论