在Java应用程序开发中,有时需要与Microsoft Access数据库进行交互,尤其是在处理一些遗留系统、小型企业应用或数据迁移项目时,Access数据库以其轻量级、易于使用的特点,在特定场景下依然有其应用价值,本文将详细介绍如何使用现代、推荐的方法——UCanAccess驱动程序,在Java中连接和操作Access数据库,并探讨相关的最佳实践与常见问题。

准备工作:环境与工具
在开始编码之前,确保您的开发环境已经准备就绪,这包括基础的Java开发工具和我们将要使用的核心库。
- Java开发工具包 (JDK):确保已安装JDK 8或更高版本,这是运行Java程序的基础。
 - 集成开发环境 (IDE):推荐使用IntelliJ IDEA或Eclipse等主流IDE,它们能极大地简化项目管理和依赖配置。
 - Microsoft Access:您需要安装Microsoft Access来创建
.mdb(旧版)或.accdb(新版)格式的数据库文件,程序运行时,客户端机器上无需安装Access。 - UCanAccess驱动程序:这是一个开源的纯Java JDBC驱动程序,允许Java程序直接读写Access数据库,无需依赖ODBC,这是目前连接Access数据库的最佳选择。
 
核心步骤:使用UCanAccess建立连接
我们将通过一个完整的示例,演示从创建数据库到Java代码实现连接、查询和插入数据的全过程。
步骤1:创建Access数据库
打开Microsoft Access,创建一个新的空白数据库,例如命名为sample.accdb,在其中创建一个名为users的表,并添加以下字段:
| 字段名 | 数据类型 | 说明 | 
|---|---|---|
| id | 自动编号 | 主键 | 
| name | 短文本 | 用户名 | 
| 短文本 | 电子邮箱 | 
为了测试,您可以手动添加一两行数据,将这个sample.accdb文件保存在您项目的一个易于访问的位置,例如项目根目录下的一个db文件夹中。
步骤2:在项目中添加UCanAccess依赖
对于使用Maven或Gradle等构建工具的项目,添加依赖非常简单,UCanAccess会自动处理其所需的传递性依赖。
Maven pom.xml 配置:
<dependencies>
    <!-- UCanAccess 核心库 -->
    <dependency>
        <groupId>net.sf.ucanaccess</groupId>
        <artifactId>ucanaccess</artifactId>
        <version>5.0.1</version> <!-- 建议使用最新稳定版 -->
    </dependency>
</dependencies>
当您添加此依赖后,Maven会自动下载UCanAccess及其必需的依赖项,如Jackcess(用于读取Access文件格式)、HSQLDB(用于提供某些SQL功能)等。

如果您不使用构建工具,需要手动下载以下JAR包并添加到项目的类路径中:
- ucanaccess-x.x.x.jar
 - jackcess-x.x.x.jar
 - hsqldb.jar
 - commons-lang3-x.x.jar
 - commons-logging-x.x.jar
 
步骤3:编写Java连接与操作代码
下面是一个完整的Java类,演示了如何连接到sample.accdb数据库,执行查询和插入操作。
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class AccessConnector {
    // 数据库文件路径(请根据您的实际路径修改)
    private static final String DB_URL = "jdbc:ucanaccess://./db/sample.accdb";
    public static void main(String[] args) {
        // 使用 try-with-resources 语句确保资源被自动关闭
        try (Connection conn = DriverManager.getConnection(DB_URL)) {
            System.out.println("成功连接到Access数据库!");
            // 1. 查询数据
            queryUsers(conn);
            // 2. 插入新数据(使用PreparedStatement防止SQL注入)
            insertNewUser(conn, "张三", "zhangsan@example.com");
            // 再次查询以验证插入结果
            System.out.println("\n插入新数据后:");
            queryUsers(conn);
        } catch (SQLException e) {
            System.err.println("数据库操作失败!");
            e.printStackTrace();
        }
    }
    private static void queryUsers(Connection conn) throws SQLException {
        String sql = "SELECT id, name, email FROM users";
        try (Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery(sql)) {
            System.out.println("--- 用户列表 ---");
            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                String email = rs.getString("email");
                System.out.printf("ID: %d, 姓名: %s, 邮箱: %s\n", id, name, email);
            }
            System.out.println("----------------");
        }
    }
    private static void insertNewUser(Connection conn, String name, String email) throws SQLException {
        String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
        try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
            pstmt.setString(1, name);
            pstmt.setString(2, email);
            int affectedRows = pstmt.executeUpdate();
            if (affectedRows > 0) {
                System.out.println("成功插入新用户:" + name);
            } else {
                System.out.println("插入用户失败。");
            }
        }
    }
}
代码解析:
- 连接字符串:
jdbc:ucanaccess://./db/sample.accdb是关键。jdbc:ucanaccess://是协议前缀,后面跟着数据库文件的绝对或相对路径。 - try-with-resources:这是Java 7引入的特性,用于自动管理资源。
Connection,Statement,ResultSet,PreparedStatement都实现了AutoCloseable接口,在try块结束后会自动调用close()方法,有效避免了资源泄漏。 - 查询:通过
createStatement()创建Statement对象,执行executeQuery()获取ResultSet,然后遍历结果集。 - 插入:使用
PreparedStatement是最佳实践,它通过预编译SQL语句并使用占位符,不仅能有效防止SQL注入攻击,而且在执行重复操作时性能更优。 
最佳实践与注意事项
连接字符串的常用参数
UCanAccess的连接字符串支持多种参数来优化连接行为,
memory=true:将数据库加载到内存中,提升读取速度,但修改不会持久化到磁盘文件,适用于只读场景。showSchema=true:在JDBC元数据中显示Access数据库的schema信息。ignoreCase=true:在比较字符串时忽略大小写。
示例:jdbc:ucanaccess://./db/sample.accdb;memory=true;ignoreCase=true
资源管理的重要性
如前所述,必须确保所有JDBC资源(Connection, Statement, ResultSet)在使用后被正确关闭,未关闭的连接会导致数据库文件被锁定,其他进程(包括Access本身)将无法打开,同时也会造成服务器内存泄漏,try-with-resources是处理此问题的最简洁、最安全的方式。
关于位数(32位/64位)的说明
使用UCanAccess的一大优势是它是一个纯Java驱动,不依赖于任何本地库,它完美地解决了经典的JDK位数与Office/Access位数不匹配的问题,无论您的JDK是32位还是64位,也无论您的Access数据库是哪个版本创建的,UCanAccess都能正常工作,这比已被淘汰的JDBC-ODBC桥接方式要可靠得多。

通过UCanAccess驱动程序,Java连接Access数据库变得简单、高效且跨平台,核心流程可以概括为:添加项目依赖、构建正确的连接字符串、使用JDBC API进行数据库操作,并始终遵循资源管理的最佳实践,对于需要与Access数据库集成的Java项目,UCanAccess无疑是当前最值得推荐的技术方案。
相关问答FAQs
问题1:为什么我的程序运行时提示“找不到合适的驱动程序”?
解答: 这个错误通常由以下两个原因之一导致:
- 依赖未正确添加:如果您使用Maven或Gradle,请检查
pom.xml或build.gradle文件中的依赖配置是否正确,并确保项目已成功重新构建和刷新,如果是手动添加JAR包,请确认所有必需的JAR文件(UCanAccess及其依赖)都已正确添加到项目的类路径中。 - 连接字符串错误:请仔细检查您的数据库连接URL,常见的错误包括协议前缀拼写错误(如写成了
jdbc:ucanaces)、数据库文件路径不正确或文件不存在,URL必须以jdbc:ucanaccess://开头。 
问题2:连接Access数据库时,是否需要在运行Java程序的服务器上安装Microsoft Office或Access?
解答: 不需要,这正是UCanAccess驱动程序的核心优势之一,UCanAccess是一个纯Java实现的库,它内置了解析Access数据库文件格式(.mdb和.accdb)的能力,您的Java应用程序只需要包含UCanAccess的JAR包,就可以直接读写数据库文件,完全不依赖于操作系统中是否安装了Office或Access的ODBC驱动程序,这使得部署更加简单和独立。