杰瑞科技汇

Java如何连接Access数据库?

准备工作

在开始编码之前,你需要确保以下几点:

Java如何连接Access数据库?-图1
(图片来源网络,侵删)

1 准备 Access 数据库文件

  1. 创建一个 Access 数据库,你可以使用 Microsoft Access 软件来创建。

  2. 在数据库中创建一张表,我们创建一个名为 students 的表,包含 id, name, age 三个字段。

  3. 向表中插入一些示例数据。

    students 表结构: | 字段名 | 数据类型 | 说明 | | :--- | :--- | :--- | | id | 自动编号 (AutoNumber) | 主键 | | name | 短文本 (Text) | 学生姓名 | | age | 数字 (Number) | 学生年龄 |

    Java如何连接Access数据库?-图2
    (图片来源网络,侵删)

    示例数据: | id | name | age | | :--- | :--- | :--- | | 1 | 张三 | 20 | | 2 | 李四 | 21 | | 3 | 王五 | 22 |

假设我们将这个数据库文件保存在 D:\database\mydb.accdb

2 下载 Access 数据库驱动

Java 通过 JDBC (Java Database Connectivity) 来连接数据库,Access 数据库需要一个 JDBC 驱动程序。

  • 对于较新的 Access 2007 及以上版本 (.accdb 文件):

    Java如何连接Access数据库?-图3
    (图片来源网络,侵删)
    • 你需要 UCanAccess 驱动,这是一个开源的、纯 Java 的 JDBC 驱动,是目前连接 .accdb 文件的最佳选择。
    • 下载地址: https://github.com/UCanAccess/UCanAccess
    • 下载最新版本的发布包(UCanAccess-5.0.4-bin.zip),解压后,你会得到一个包含多个 .jar 文件的文件夹。
  • 对于较旧的 Access 2003 及以下版本 (.mdb 文件):

    • 你需要 Microsoft Access Database Engine,这个驱动包含本地库(不是纯 Java),因此你的 Java 应用程序在运行时需要访问这些本地库。
    • 下载地址: https://www.microsoft.com/en-us/download/details.aspx?id=54920
    • 注意: 32位和64位的驱动不同,请根据你的 Java 运行环境 和操作系统 选择正确的版本,如果出现 java.lang.UnsatisfiedLinkError 错误,通常就是驱动位数不匹配导致的。

3 配置项目依赖

将下载的驱动库文件添加到你的项目中。

  • 如果你使用 Maven (推荐): UCanAccess 可以通过 Maven 中央仓库获取,这是最简单的方式,在 pom.xml 中添加以下依赖:

    <dependencies>
        <!-- UCanAccess JDBC Driver for Access .accdb files -->
        <dependency>
            <groupId>com.github.u-can-access</groupId>
            <artifactId>ucanaccess</artifactId>
            <version>5.0.4</version> <!-- 使用最新版本 -->
        </dependency>
    </dependencies>
  • 如果你手动管理 JAR 文件:

    1. 将 UCanAccess 解压包中的 所有 .jar 文件(如 ucanaccess-5.0.4.jar, hsqldb.jar, jackcess-5.0.4.jar 等)添加到你的项目的类路径(Classpath)中。
    2. 如果你使用的是旧版的 .mdb 驱动,通常只需要 msaccess.jarjdbcodbc.jar(如果使用 JDBC-ODBC 桥接)。

Java 代码示例

下面是使用 UCanAccess 连接 .accdb 文件并执行基本操作的完整代码。

1 数据库连接 URL 格式

UCanAccess 的连接 URL 有固定的格式:

jdbc:ucanaccess://<数据库文件的完整路径>
  • <数据库文件的完整路径>:指向你的 .accdb.mdb 文件的绝对路径。

2 完整代码示例

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class AccessDBExample {
    // 数据库文件路径 - 请务必修改为你自己的路径
    private static final String DB_URL = "jdbc:ucanaccess://D:/database/mydb.accdb";
    public static void main(String[] args) {
        // try-with-resources 语句,确保连接、语句和结果集在使用后被自动关闭
        try (Connection conn = DriverManager.getConnection(DB_URL);
             Statement stmt = conn.createStatement()) {
            System.out.println("成功连接到 Access 数据库!");
            // 1. 查询数据
            System.out.println("\n--- 查询所有学生信息 ---");
            queryStudents(stmt);
            // 2. 插入数据
            System.out.println("\n--- 插入一条新学生记录 ---");
            insertStudent(stmt, "赵六", 23);
            // 再次查询以验证插入
            queryStudents(stmt);
            // 3. 更新数据
            System.out.println("\n--- 更新学生信息 (将李四的年龄改为 22) ---");
            updateStudentAge(stmt, "李四", 22);
            queryStudents(stmt);
            // 4. 删除数据
            System.out.println("\n--- 删除学生信息 (删除王五) ---");
            deleteStudent(stmt, "王五");
            queryStudents(stmt);
        } catch (SQLException e) {
            System.err.println("数据库操作出错: " + e.getMessage());
            e.printStackTrace();
        }
    }
    // 查询学生信息
    private static void queryStudents(Statement stmt) throws SQLException {
        String sql = "SELECT id, name, age FROM students";
        try (ResultSet rs = stmt.executeQuery(sql)) {
            System.out.println("ID\t姓名\t年龄");
            System.out.println("--------------------");
            while (rs.next()) {
                // 通过列名获取数据,可读性更好,且与列的顺序无关
                int id = rs.getInt("id");
                String name = rs.getString("name");
                int age = rs.getInt("age");
                System.out.println(id + "\t" + name + "\t" + age);
            }
        }
    }
    // 插入学生信息
    private static void insertStudent(Statement stmt, String name, int age) throws SQLException {
        // 注意:对于自动编号字段,不需要在SQL中指定
        String sql = String.format("INSERT INTO students (name, age) VALUES ('%s', %d)", name, age);
        int affectedRows = stmt.executeUpdate(sql);
        if (affectedRows > 0) {
            System.out.println("成功插入 " + affectedRows + " 行数据。");
        } else {
            System.out.println("插入数据失败。");
        }
    }
    // 更新学生年龄
    private static void updateStudentAge(Statement stmt, String name, int newAge) throws SQLException {
        String sql = String.format("UPDATE students SET age = %d WHERE name = '%s'", newAge, name);
        int affectedRows = stmt.executeUpdate(sql);
        if (affectedRows > 0) {
            System.out.println("成功更新 " + affectedRows + " 行数据。");
        } else {
            System.out.println("未找到名为 " + name + " 的学生,更新失败。");
        }
    }
    // 删除学生信息
    private static void deleteStudent(Statement stmt, String name) throws SQLException {
        String sql = String.format("DELETE FROM students WHERE name = '%s'", name);
        int affectedRows = stmt.executeUpdate(sql);
        if (affectedRows > 0) {
            System.out.println("成功删除 " + affectedRows + " 行数据。");
        } else {
            System.out.println("未找到名为 " + name + " 的学生,删除失败。");
        }
    }
}

重要注意事项和最佳实践

1 SQL 注入风险

上面的示例中,我们使用了 String.format 来拼接 SQL 语句,这种方式极易受到 SQL 注入攻击,如果 name 参数是 ' OR '1'='1,那么查询语句就变成了 SELECT * FROM students WHERE name = '' OR '1'='1',会返回所有记录。

正确做法是使用 PreparedStatement

// 安全的插入方法示例
private static void safeInsertStudent(Connection conn, String name, int age) throws SQLException {
    String sql = "INSERT INTO students (name, age) VALUES (?, ?)";
    try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
        pstmt.setString(1, name);
        pstmt.setInt(2, age);
        int affectedRows = pstmt.executeUpdate();
        System.out.println("安全插入 " + affectedRows + " 行数据。");
    }
}

PreparedStatement 会对输入参数进行转义,从根本上防止 SQL 注入。

2 资源管理

数据库连接(Connection)、语句(Statement/PreparedStatement)和结果集(ResultSet)都是需要系统资源的重要对象,使用完毕后必须关闭它们。

  • 传统方式:finally 块中手动关闭。
  • 推荐方式: 使用 try-with-resources 语句(如示例代码所示),它会自动在 try 块执行完毕后调用这些对象的 close() 方法,代码更简洁、安全。

3 数据库文件锁定

Access 是一个文件数据库,当你的 Java 程序连接到它时,数据库文件会被锁定,这意味着:

  • 不能同时用 Access 软件和你的 Java 程序打开同一个数据库文件,否则会抛出错误。
  • 如果程序异常终止,可能会导致数据库文件处于锁定状态,下次连接时会失败,通常需要手动删除同目录下的 .laccdb 锁定文件。

4 性能考虑

Access 数据库不适合高并发的场景,如果你的应用需要同时处理大量请求,请考虑使用客户端-服务器模式的数据库,如 MySQL, PostgreSQL, SQL Server 等。


常见问题 (FAQ)

Q1: 运行时出现 ClassNotFoundException 错误。

原因: JVM 找不到 JDBC 驱动的类。 解决方案:

  1. 确保你已经下载了正确的驱动 JAR 文件。
  2. 确保你已经将这些 JAR 文件正确地添加到了项目的类路径中,如果你使用 IDE(如 IntelliJ IDEA 或 Eclipse),请检查项目的库配置。

Q2: 运行时出现 java.lang.UnsatisfiedLinkError 错误。

原因: 这个错误在使用旧版 Access 驱动(非纯 Java)时非常常见,它表示 Java 无法加载本地库(如 .dll 文件)。 解决方案:

  1. 首选方案: 切换到 UCanAccess,它是纯 Java 的,没有这个问题。
  2. 如果必须使用旧版驱动,请确保:
    • 你的 Java 运行环境(JRE)的位数(32位或64位)与 Access Database Engine 的位数完全一致
    • 本地库文件(如 .dll)所在的路径在系统的 PATH 环境变量中,或者 Java 的 java.library.path 中。

Q3: 连接字符串写错了,或者数据库文件路径不对。

原因: DB_URL 中的路径不正确。 解决方案:

  1. 检查路径是否是绝对路径(从盘符开始的完整路径)。
  2. 确保路径中的分隔符是正确的,在 Java 字符串中,Windows 路径的反斜杠 \ 是一个转义字符,所以需要写成 D:\\database\\mydb.accdb 或者使用正斜杠 D:/database/mydb.accdb,后者在 Windows 和 Java 中都能正常工作,推荐使用。

希望这份详细的指南能帮助你成功地在 Java 中连接和使用 Access 数据库!

分享:
扫描分享到社交APP
上一篇
下一篇