JSP连接ACCESS数据库实战:UCanAccess与JDBC-ODBC选型及避坑指南 简介这份资源面向JSP初学者与Web开发入门者聚焦小型项目或教学实践中JSP与ACCESS数据库的基础数据交互问题。包内共1个doc文档约31KB以图文与代码示例讲解如何创建test.mdb数据库及username表将数据库文件放入Tomcat指定目录并编写JDBCAccess.jsp完成连接与数据读取。内容涵盖JDBC-ODBC桥驱动加载、连接字符串拼接、Statement与ResultSet使用以及资源关闭等关键环节同时提示ACCESS在企业级应用中的局限并对比MySQL、Oracle等数据库的连接差异。已有239人学习适合希望理解JDBC原理、快速跑通JSP访问ACCESS流程的读者参考。1. JSP 连接 ACCESS 数据库为什么老项目还在用新项目要不要碰接手一个 2010 年前后的内部管理系统服务器上跑着 Tomcat 6数据库是一个.mdb文件需求是加一个「设备借用登记」页面。你打开项目一看数据源配置里写着jdbc:odbc:driver{Microsoft Access Driver (*.mdb)}连密码都没有。这就是 JSP 连接 ACCESS 数据库最典型的场景——不是因为它好而是因为它已经在那儿了。ACCESS 是文件型数据库单文件、零服务、拷走就能跑适合单机或极小并发个位数同时在线的内部工具。JSP 作为服务端页面技术通过 JDBC-ODBC 桥或 UCanAccess 纯 Java 驱动读写.mdb/.accdb。这套组合能解决「不想装 MySQL、不想配服务、只想快速出增删改查页面」的问题适合维护老系统、做课程设计、写小型内部登记工具的人。不适合高并发、多用户写入、需要事务隔离的生产系统——这一点必须先说清楚否则后面全是坑。2. 两条连接路线JDBC-ODBC 桥与 UCanAccess 怎么选2.1 先搞清楚 ACCESS 驱动在 JDK 里的命运JDK 8 之前sun.jdbc.odbc.JdbcOdbcDriver是内置的写一行Class.forName(sun.jdbc.odbc.JdbcOdbcDriver)就能连。JDK 8 开始这个桥被标记废弃JDK 11 之后彻底移除。所以如果你现在用 JDK 8 以上JDBC-ODBC 桥这条路基本走不通除非你手动把rt.jar里的相关类抽出来——不推荐维护成本高。常见做法是改用 UCanAccess这是一个纯 Java 的 ACCESS 驱动底层用 Jackcess 库直接读.mdb/.accdb文件不依赖操作系统的 ODBC 数据源。它支持 JDK 8 到 JDK 17Maven 坐标是net.sf.ucanaccess:ucanaccess。选它的理由很直接跨平台、不装驱动、不配 DSN、代码里写 JDBC URL 就能跑。如果你维护的是 JDK 6/7 的老项目且服务器是 Windows那 JDBC-ODBC 桥还能用配置 ODBC 数据源反而更省事——因为老代码里可能已经写死了jdbc:odbc:xxx。两条路线的对比如下对比项JDBC-ODBC 桥UCanAccess依赖系统 ODBC 数据源 JDK 内置桥纯 Java jar 包JDK 支持JDK 8 以下JDK 8 及以上跨平台仅 Windows全平台部署复杂度需在服务器配 DSN拷 jar 即可并发能力差差本质一样推荐场景维护 JDK 7 老项目新写或升级项目2.2 UCanAccess 的最小可运行配置先加依赖。Maven 项目在pom.xml里写dependency groupIdnet.sf.ucanaccess/groupId artifactIducanaccess/artifactId version5.0.1/version /dependency如果你不用 Maven需要手动下载这几个 jar 放进WEB-INF/libucanaccess、jackcess、commons-lang3、commons-logging、hsqldb。少一个都会在运行时报ClassNotFoundException这是血泪经验。然后写一个连接工具类import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; public class AccessConn { // ACCESS 文件放在 WEB-INF/db 下避免被直接下载 private static final String DB_PATH D:/project/webapp/WEB-INF/db/device.mdb; private static final String URL jdbc:ucanaccess:// DB_PATH ;memoryfalse; public static Connection getConnection() throws SQLException { try { Class.forName(net.ucanaccess.jdbc.UcanaccessDriver); } catch (ClassNotFoundException e) { throw new SQLException(UCanAccess 驱动未找到, e); } return DriverManager.getConnection(URL); } }逻辑说明jdbc:ucanaccess://后面跟绝对路径memoryfalse表示不把整个库加载进内存——对于几十 MB 的.mdb设true会快一点但内存占用高设false每次读磁盘适合文件不大但内存紧张的场景。参数DB_PATH必须用绝对路径相对路径在 Tomcat 里会相对于bin目录不是你的项目目录这是新手最容易翻车的地方。2.3 JDBC-ODBC 桥的配置步骤仅限 JDK 7 及以下如果你确实在老环境里步骤是控制面板 → 管理工具 → ODBC 数据源32 位→ 系统 DSN → 添加 → 选Microsoft Access Driver (*.mdb)→ 填数据源名比如devdb→ 选文件。然后 Java 代码里Class.forName(sun.jdbc.odbc.JdbcOdbcDriver); Connection conn DriverManager.getConnection(jdbc:odbc:devdb, , );注意 Tomcat 如果是 64 位ODBC 数据源也必须配 64 位的否则报[Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序。这个报错我见过太多次原因就是 32 位 DSN 配了 64 位 Tomcat。3. 在 JSP 里写增删改查从建表到分页展示3.1 建表与字段类型映射ACCESS 的字段类型和 Java 类型对应关系要心里有数否则getObject会给你惊喜ACCESS 类型Java 读取方式注意文本短文本rs.getString()长度默认 255备注长文本rs.getString()可能返回null数字长整型rs.getLong()自增主键用这个日期/时间rs.getTimestamp()格式敏感是/否rs.getBoolean()ACCESS 里存 -1/0OLE 对象rs.getBytes()存图片用不推荐建表可以在 ACCESS 界面里手动建也可以用 SQL 在 JSP 里建。手动建更稳因为 UCanAccess 对CREATE TABLE的语法支持有限比如AUTOINCREMENT关键字有时不认。我一般建议在 ACCESS 里建好表JSP 只做增删改查。3.2 查询与分页的 JSP 片段下面是一个设备列表分页查询的 JSP 核心代码% page importjava.sql.*, com.example.AccessConn % % int pageSize 10; int pageNo 1; String p request.getParameter(page); if (p ! null) pageNo Integer.parseInt(p); int offset (pageNo - 1) * pageSize; String sql SELECT id, name, status FROM device ORDER BY id DESC; Connection conn null; PreparedStatement ps null; ResultSet rs null; try { conn AccessConn.getConnection(); // ACCESS 不支持 LIMIT OFFSET用绝对定位模拟 ps conn.prepareStatement(sql, ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_READ_ONLY); rs ps.executeQuery(); rs.absolute(offset 1); // 定位到本页第一条 int count 0; while (rs.next() count pageSize) { count; % tr td% rs.getLong(id) %/td td% rs.getString(name) %/td td% rs.getInt(status) 1 ? 在用 : 停用 %/td /tr % } } catch (Exception e) { out.println(查询失败 e.getMessage()); } finally { if (rs ! null) rs.close(); if (ps ! null) ps.close(); if (conn ! null) conn.close(); } %逻辑说明ACCESS 的 SQL 方言不支持LIMIT和OFFSET所以分页要用ResultSet的滚动游标。TYPE_SCROLL_INSENSITIVE允许absolute()定位CONCUR_READ_ONLY减少锁开销。rs.absolute(offset 1)把游标移到本页第一条然后循环取pageSize条。参数pageSize建议不超过 20因为 ACCESS 文件锁在并发读时表现很差一次取太多会拖慢响应。3.3 插入、更新、删除的写法与事务增删改都用PreparedStatement不要拼字符串否则单引号就能让你的页面崩掉public static int addDevice(String name, int status) throws SQLException { String sql INSERT INTO device (name, status) VALUES (?, ?); try (Connection conn AccessConn.getConnection(); PreparedStatement ps conn.prepareStatement(sql)) { ps.setString(1, name); ps.setInt(2, status); return ps.executeUpdate(); } }更新和删除同理把 SQL 换成UPDATE device SET name? WHERE id?或DELETE FROM device WHERE id?。注意 ACCESS 的executeUpdate返回受影响行数但有时因为文件锁会返回 0 而不报错所以业务层要再查一次确认。事务方面ACCESS 支持conn.setAutoCommit(false)和commit()但并发写入时容易死锁。我的做法是单条增删改不显式开事务靠自动提交批量操作才开事务且加conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED)。即便如此两个用户同时写同一个.mdb仍可能报Could not update; currently locked这是 ACCESS 的硬限制不是代码问题。4. 避坑与排查ACCESS 连接最常见的 5 个翻车现场4.1 报错[Microsoft][ODBC 驱动程序管理器] 未发现数据源名称现象JSP 页面抛出这个异常堆栈指向DriverManager.getConnection。原因ODBC 数据源没配或者配的位数和 Tomcat 不一致。32 位 DSN 在 64 位 JVM 里不可见反之亦然。解决确认 Tomcat 的位数java -version看 64-Bit 字样然后去C:\Windows\SysWOW64\odbcad32.exe32 位或C:\Windows\System32\odbcad32.exe64 位配对应的系统 DSN。配完重启 Tomcat。4.2 报错UCanAccessDriver not found现象Maven 依赖加了但运行时报ClassNotFoundException: net.ucanaccess.jdbc.UcanaccessDriver。原因UCanAccess 依赖链没打全缺jackcess或hsqldb。Maven 有时因为仓库问题只下了主包。解决在pom.xml里显式加jackcess和hsqldb依赖或者用mvn dependency:copy-dependencies把所有传递依赖拷到WEB-INF/lib。检查WEB-INF/lib下至少有 5 个相关 jar。4.3 报错Could not update; currently locked现象多人同时操作时插入或更新失败提示文件被锁。原因ACCESS 是文件锁一个写操作会锁整个文件其他写操作排队或直接失败。解决把memoryfalse改成memorytrue让 UCanAccess 用内存副本减少文件锁时间或者用conn.setAutoCommit(true)尽快释放锁。根本方案是换数据库如果并发超过 5 个人ACCESS 就不该继续用。4.4 中文乱码现象JSP 页面显示的中文变成???或乱码。原因ACCESS 文件本身编码、JDBC URL 没指定字符集、JSP 页面pageEncoding不一致。解决JSP 顶部写% page contentTypetext/html;charsetUTF-8 pageEncodingUTF-8 %UCanAccess 的 URL 加;charSetUTF-8ACCESS 建表时字段用「短文本」而不是「备注」备注字段在某些驱动版本下编码处理有问题。4.5 日期格式写入失败现象ps.setTimestamp()写入 ACCESS 日期字段时报Data type mismatch。原因ACCESS 的日期字段对格式敏感java.sql.Timestamp在某些驱动版本下不被识别。解决改用ps.setString()传yyyy-MM-dd HH:mm:ss格式的字符串ACCESS 会自动转换。或者用ps.setObject()传java.util.Date让驱动自己处理。我一般用字符串最稳。5. 进阶技巧用连接池和只读模式把 ACCESS 压榨到极限ACCESS 本身不支持连接池但你可以用 DBCP 或 HikariCP 包一层减少频繁打开文件的开销。配置 HikariCP 的maximumPoolSize设 3 到 5connectionTimeout设 3000 毫秒idleTimeout设 60000。超过 5 个连接反而会因为文件锁互相等待性能下降。另一个技巧是只读模式。如果页面只做展示UCanAccess 的 URL 加;readonlytrue这样多个请求可以同时读不会互相锁。写操作单独走一个连接读写分离在 ACCESS 层面也能凑合实现。验证方法用 JMeter 开 10 个线程循环请求列表页观察响应时间。如果平均超过 500 毫秒说明文件锁在拖后腿这时候要么加缓存把查询结果放application作用域定时刷新要么换 SQLite——SQLite 的并发读比 ACCESS 好迁移成本也不高。我自己的习惯是新项目一律不选 ACCESS老项目维护时先确认 JDK 版本JDK 8 以上直接上 UCanAccessJDK 7 以下才考虑 ODBC 桥。每次改完连接代码先在本机用main方法跑一遍增删改查再部署到 Tomcat能省掉一半的调试时间。希望帮到你。本文还有配套的精品资源点击获取