资讯动态

JSP连接Access数据库:JDBC-ODBC桥配置、驱动排错与上线自检

发布时间:2026/10/25 1:07:28 来源:尧图企业网站定制
简介这份文档面向JSP入门学习者与小型Web项目开发者围绕JSP通过JDBC-ODBC桥连接ACCESS数据库这一基础数据交互方式展开帮助读者理解在Tomcat环境下完成数据库访问的完整思路。文档先从建库入手说明如何创建test.mdb及username表含uid、pwd两个文本字段再讲解将数据库文件放入Tomcat的webapps/ROOT/data目录并借助application.getRealPath转换为物理路径的做法最后给出JDBCAccess.jsp示例逐段解析加载sun.jdbc.odbc.JdbcOdbcDriver、拼接连接字符串、创建Statement、执行查询、遍历ResultSet并输出用户名与密码以及依次关闭ResultSet、Statement和Connection的要点同时对易出错的连接异常给出提示信息。资源包共1个文件为doc文档大小约31KB篇幅精炼、代码与说明对照适合边看边在本地复现调试。目前已有240人学习可作为理解JDBC与数据库交互原理的入门参考。1. 从一份打不开的老页面说起JSP 连接 ACCESS 数据库到底解决什么问题接手一个早年的课程设计包首页只有一行红字java.sql.SQLException: [Microsoft][ODBC 驱动程序管理器] 未发现数据源名称并且未指定默认驱动程序。这套 JSP 连接 ACCESS 数据库的示例链路其实很短页面里用Class.forName加载sun.jdbc.odbc.JdbcOdbcDriverDriverManager拿ConnectionSQL 交给Statement结果集用while(rs.next())逐行out.print。一个.mdb文件加一个 Tomcat 就能跑不用另装数据库服务也不用配账号体系。它适合谁课程设计、单机演示、内网小后台、离线数据查看页这类读写量极低的场景。不适合高并发写入Access 是文件型数据库几个连接同时写就锁表。下面按建库、放文件、写连接串、调页面、排错的顺序拆每一步都给可对照的参数。2. 建库与落盘把 test.mdb 放到 Tomcat 能找到的位置2.1 建库建表字段类型与命名约定先在 Access 里新建一个空数据库另存为test.mdb。这里有个容易被忽略的点Access 2007 之后的默认保存格式是.accdb如果你直接点保存拿到的是.accdb文件而示例里的连接串写的是(*.mdb)驱动名对不上就会报「未发现数据源名称」。新建时在「另存为」对话框里把文件类型切回「Access 2002-2003 数据库 (*.mdb)」或者建完之后用「数据库工具 → 转换数据库」降级一次。建表这一步表名定为username两个字段字段名数据类型字段大小允许空说明uid文本50是登录名示例里直接当用户名打印pwd文本50是明文密码仅演示用id自动编号长整型否可选建议加方便后续排序「文本」在 Access 里对应的是Text/VARCHAR不是「备注」。如果误选成「备注」MemoJDBC 读出来是长文本对象rs.getString()虽然还能取到值但排序和比较会出幺蛾子。字段大小设 50 是留余量Access 的文本型上限是 255超过就得换备注型。表名和字段名都别用 Access 保留字password、date、value、level、order这几个都是雷区写在 SQL 里必须加方括号[password]不加就报语法错误。示例用pwd是聪明的做法我一般也这么起名。字段名大小写在 Access 里不敏感但 JSP 里rs.getString(uid)的字符串要和建表时一致养成小写习惯最省事。建完表随手插两行测试数据别等到页面跑起来才发现表是空的——空表也能连上你会误以为整条链路通了其实查询逻辑根本没验证过。2.2 数据库放哪getRealPath 与 webapps/ROOT/data 的对应关系示例把数据库放在%TOMCAT_HOME%\webapps\ROOT\data\test.mdb代码里写的是相对路径data/test.mdb中间靠application.getRealPath(spath)转成物理路径。这三者的对应关系必须拧成一股%TOMCAT_HOME%\webapps\ROOT\ ← Web 应用根目录也就是 context 的 docBase └─ data\ └─ test.mdb ← 实际文件application.getRealPath(data/test.mdb)返回的是...\webapps\ROOT\data\test.mdb。注意getRealPath的参数是相对于 Web 应用根的前面不能带斜杠写成/data/test.mdb在某些容器版本上也能对但跨版本行为不一致老老实实写相对路径。两个坑提前说。第一getRealPath在应用以未解压的 war 包形式部署时可能返回null因为容器没有真实目录可映射。开发阶段直接丢文件夹到webapps下最稳别一上来就打 war。第二放data目录意味着这个文件在 Web 根下浏览器直接访问/data/test.mdb就能把整库下载走。课程设计无所谓真上线要把库挪到WEB-INF下或者容器外的固定目录再把代码里的路径改成绝对路径。application是 JSP 的内置对象本质是ServletContext生命周期跟着应用走。用它取路径的好处是换机器、换 Tomcat 安装位置都不用改代码只要目录结构保持一致。2.3 运行前提JDK、Tomcat 与 ODBC 驱动的版本账这套写法最要命的地方在版本不在代码。sun.jdbc.odbc.JdbcOdbcDriver属于 JDBC-ODBC 桥从 JDK 7 起被标记为废弃JDK 8 直接移除。也就是说如果你现在用 JDK 8 及以上跑这段代码Class.forName那一行必定抛ClassNotFoundException跟数据库、路径、权限都没关系。组件可用区间检查方式超出区间后的表现JDK6 及以下含桥驱动java -version8 抛 ClassNotFoundExceptionTomcat6/7/8 均可配 JDK 6启动日志首行高版本 Tomcat 要求 JDK 8与桥驱动冲突Access ODBC 驱动随 Office 或 Access Database Engine 安装ODBC 数据源管理器里看「驱动程序」页列表里没有对应项连接串直接失败位数JVM 位数 ODBC 驱动位数任务管理器看进程、ODBC 管理器标题栏32 位 JVM 看不到 64 位数据源反之亦然现实的做法有两条。一条是把运行环境压到 JDK 6 Tomcat 6/7虚拟机或旧机器上跑纯当教学演示。另一条是换驱动用第三方的 UCanAccess 或 Jackcess 之类的纯 Java 库替代 ODBC 桥连接串格式完全不同但能在新 JDK 上跑。哪条都行唯一不能做的是拿 JDK 8 硬套这份代码然后怀疑人生。Windows 上找 ODBC 管理器要分清两个入口控制面板里的「ODBC 数据源32 位」和「ODBC 数据源64 位」。名字很像点错了配出来的 DSN 在程序里就是看不见这是后面排错章节的头号案例。3. 连接串两种写法DBQ 直连与 DSN 配置的参数拆解3.1 DBQ 直连一条 URL 里每个分号的含义示例用的是直连写法不依赖任何预先配置的数据源把驱动名和文件路径都塞进 URL// Access 数据库相对路径相对的是 Web 应用根目录 String spath data/test.mdb; // 转成服务器上的绝对物理路径ODBC 只认绝对路径 String dbpath application.getRealPath(spath); // 驱动名必须和 ODBC 管理器「驱动程序」页里显示的名字逐字一致 // .mdb 用这一条.accdb 要换成 {Microsoft Access Driver (*.mdb, *.accdb)} String url jdbc:odbc:Driver{Microsoft Access Driver (*.mdb)};DBQ dbpath;拆开看三段。jdbc:odbc:是协议前缀告诉DriverManager找桥驱动。Driver{...}是 ODBC 层的驱动标识花括号里那一串是一个完整名字逗号、空格、星号、括号全都算数少一个字符就报「未发现数据源名称」——这个报错极具迷惑性因为它字面上在说数据源实际是在说驱动名没匹配上。DBQ后面跟数据库文件的绝对路径路径里有空格没关系ODBC 会整体处理但如果路径里带分号就会被当成参数分隔符截断这种目录名趁早改掉。还有一个常被问到的参数dbname示例里定义了String dbname ;却没用上。它是给 DSN 写法留的位置直连模式下不需要。同理user和password在没给 Access 设密码时都传空串设了密码就要对着填Access 的库密码和用户级安全机制是两回事前者才是连接串要的。3.2 系统 DSN 写法什么时候必须去控制面板配数据源另一条路是先在系统里注册一个数据源URL 只写名字// DSN 名称就是 ODBC 管理器里「名称」那一栏填的值大小写不敏感 String url jdbc:odbc:testdsn; // 连接时把账号密码单独传Access 无密码就传空串 Connection conn DriverManager.getConnection(url, user, password);配置路径是控制面板 → 管理工具 → ODBC 数据源 → 选「系统 DSN」页 → 添加 → 选Microsoft Access Driver (*.mdb)→ 名称填testdsn→ 点「选择」定位到test.mdb。系统 DSN 对本机所有用户生效用户 DSN 只对当前登录用户生效Tomcat 如果注册成了 Windows 服务跑在系统账户下用用户 DSN 就会看不见这个坑后面还会提。两种写法怎么选直连适合开发调试改路径只改代码不污染系统环境DSN 适合多套应用共用一个库路径变了只改一处配置。直连的代价是每次连接都要解析驱动名理论上稍慢但在这个量级的应用里测不出来。3.3 驱动名与位数的对应关系驱动名不是随便写的要跟文件格式、Office 版本对上文件格式驱动名常见来源.mdb{Microsoft Access Driver (*.mdb)}旧版 Office / Access 运行时.mdb 与 .accdb 混用{Microsoft Access Driver (*.mdb, *.accdb)}Access Database Engine 2010 及以上.accdb 且无旧驱动同上同上注意位数装完驱动后打开 ODBC 管理器切到「驱动程序」页把那一列名字复制出来和代码里的字符串做逐字比对比靠记忆靠谱得多。名字对不上就是「未发现数据源名称」名字对上了但位数不对报错会变成「找不到指定的文件」或者干脆挂住这两种错长得完全不一样别混为一谈。4. 页面实现从加载驱动到结果集遍历的逐行对照4.1 页面指令与编码声明gb2312 这一行不能省% page contentTypetext/html; charsetgb2312 languagejava importjava.sql.*% meta http-equivContent-Type contenttext/html; charsetgb2312page指令里importjava.sql.*是必须的少了Connection、Statement、ResultSet全部找不到符号。contentType和charset决定响应头里的编码meta决定浏览器解析编码两处写同一个值才不打架。用gb2312是早年环境的惯例对应的是 JDK 6 时代中文 Windows 的默认编码。如果服务器默认编码是 UTF-8而页面声明 gb2312out.print出来的中文就会变成一串问号。我一般会把三处编码统一成UTF-8page指令的charset、meta的charset、以及文件本身的保存编码。三处不一致是最典型的乱码来源。4.2 完整 JSP从加载驱动到关闭连接% page contentTypetext/html; charsetUTF-8 languagejava importjava.sql.*% % Connection conn null; Statement stmt null; ResultSet rs null; try { // 1. 拼数据库物理路径相对 Web 应用根目录 String spath data/test.mdb; String dbpath application.getRealPath(spath); if (dbpath null) { out.print(路径解析失败应用可能以 war 包形式未解压部署); return; } // 2. 直连式连接串驱动名与 ODBC 驱动程序页逐字一致 String url jdbc:odbc:Driver{Microsoft Access Driver (*.mdb)};DBQ dbpath; // 3. 加载 JDBC-ODBC 桥驱动仅 JDK 6 及以下有效 Class.forName(sun.jdbc.odbc.JdbcOdbcDriver); // 4. 建立连接无密码则账号密码都为空串 conn DriverManager.getConnection(url); // 5. 创建可滚动、可更新的语句对象 stmt conn.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); // 6. 查询并逐行输出字段名要和建表时一致 String sql select uid, pwd from username; rs stmt.executeQuery(sql); while (rs.next()) { out.print(用户名: rs.getString(uid)); out.print( 密码: rs.getString(pwd) br); } out.print(br数据库连接成功); } catch (Exception e) { // 打印异常类型比只打 message 更容易定位 out.print(数据库连接错误 e.getClass().getName() br); out.print(e.getMessage()); } finally { // 关闭顺序必须是 结果集 → 语句 → 连接 if (rs ! null) { try { rs.close(); } catch (Exception ignored) {} } if (stmt ! null) { try { stmt.close(); } catch (Exception ignored) {} } if (conn ! null) { try { conn.close(); } catch (Exception ignored) {} } } %和原始示例相比改了三处。第一连接、语句、结果集三个变量提到try外面声明finally里才能关到原始代码把close()写在try末尾一旦查询中途抛异常后面的close全部跳过连接就漏了。第二finally里每个close单独try-catch避免第一个关闭失败导致后面两个不执行。第三catch里多打了一行异常类名ClassNotFoundException和SQLException的处理方向完全不同先分清类型再查。4.3 逐段对照每行代码失败时看什么application.getRealPath返回null时大概率是 war 未解压部署或者参数写成了以斜杠开头的绝对路径。先在页面里把dbpath打出来看实际值再去文件管理器里核对该路径下test.mdb是否存在这一步能干掉一半的「找不到文件」。Class.forName抛ClassNotFoundException只有两种可能JDK 版本过高8 及以上或者类名拼错。JDK 8 之后这个类彻底不存在改环境或换驱动别在类名上打转。DriverManager.getConnection抛SQLException看 message 里的中括号内容。[Microsoft][ODBC 驱动程序管理器]开头说明卡在 ODBC 层问题是驱动名或 DSN[Microsoft][ODBC Microsoft Access Driver]开头说明驱动找到了问题在文件路径、权限或文件损坏。executeQuery抛异常基本是 SQL 写错或表名不对把sql变量打出来粘到 Access 的查询设计器里跑一遍最快。createStatement那两个参数决定结果集能不能rs.first()、rs.absolute(n)这类前后滚动操作。示例里用了可滚动可更新实际只做遍历的话传空参conn.createStatement()就够了开销更小。可更新模式还要求查询必须是单表、带主键多表关联时会直接降级或报错用不上就别开。5. 避坑与排查驱动、位数、路径、编码的五类翻车现场5.1 类找不到ClassNotFoundException 的三个来源现象页面刚打开就抛java.lang.ClassNotFoundException: sun.jdbc.odbc.JdbcOdbcDriver连数据库文件都还没碰到。原因一是 JVM 是 JDK 8 及以上桥驱动已被移除二是类名少写或多写了包路径比如写成JdbcOdbcDriver三是老项目里有人把rt.jar换成了精简版 JRE里面剔掉了sun.jdbc.odbc包。解决先java -version确认版本8 以上直接判定为环境不匹配要么换 JDK 6要么改走纯 Java 驱动。别去网上找JdbcOdbcDriver的 jar 包往WEB-INF/lib里塞那个包依赖 JNI 本地库单塞一个 class 文件跑不起来这是血泪经验。5.2 位数不匹配ODBC 里能看到数据源程序却连不上现象在 ODBC 管理器里明明配好了 DSN测试连接也通过JSP 一跑就报「未发现数据源名称」或者「找不到指定的驱动程序」。原因JVM 位数和 ODBC 驱动位数不一致。64 位 JVM 只会去找 64 位 ODBC 管理器里注册的数据源而多数人顺手打开的是 32 位那个入口配出来的东西 64 位进程完全看不见。解决确认 Tomcat 跑在哪个位数上——看java -version输出里有没有64-Bit或者任务管理器里进程名后面有没有(32 位)。然后打开同名位数的 ODBC 管理器重新配一遍。这一步没有捷径两个入口的界面长得一模一样只能靠标题栏区分。我一般会在桌面各留一个快捷方式省得每次翻控制面板翻错。5.3 路径与权限getRealPath 返回 null 和只读目录现象一页面输出「路径解析失败」dbpath是null。原因应用打成了 war 包且容器没解压getRealPath没有真实目录可映射。解决开发期直接把文件夹丢进webapps下或者改配置让容器解压 war。现象二路径正确、文件存在仍然报「找不到指定的文件」或「操作必须使用一个可更新的查询」。原因test.mdb所在目录对运行 Tomcat 的账户没有写权限。Access 打开数据库时会在同目录生成.ldb锁文件目录只读就写不了锁连接直接失败。解决给data目录加上运行账户的修改权限。把 Tomcat 注册成 Windows 服务后它跑在系统账户下和你当前登录用户不是一个人权限要单独给。5.4 中文乱码页面、连接串、字段三处编码现象数据库里存的是「张三」页面显示成??或者一串方块。原因有三层。页面层的page指令、meta标签、文件实际保存编码三者不一致数据层 Access 的文本字段本身没有编码概念但经由 ODBC 桥传输时会按系统默认代码页转换输出层out.print用的响应编码和浏览器解析编码不一致。解决先把三处页面编码统一成UTF-8文件用编辑器另存为 UTF-8 无 BOM。如果还是乱码检查 JVM 的file.encoding启动参数里加-Dfile.encodingUTF-8。桥驱动这一层对中文的支持取决于系统区域设置非中文 Windows 上跑中文数据乱码几乎是玄学最省事的办法是容器和数据库放同一台机器、同一个区域设置下。5.5 连接泄漏Tomcat 跑几天就卡死现象刚部署时一切正常跑一段时间之后页面越来越慢最后全部超时重启 Tomcat 又好了。原因原始代码把rs.close()、stmt.close()、conn.close()写在try块末尾任何一步抛异常后面的关闭全部跳过。Access 对同时打开的连接数有上限漏几十个之后新连接就建不起来了而且.ldb锁文件会一直挂着。解决按 4.2 的写法变量提到try外、关闭放finally、每个close单独捕获异常。另外别在循环里反复getConnection一个请求拿一个连接、用完就还这是底线。要更稳就上连接池但 Access 这种文件库配连接池收益有限池子开大了反而更容易撞锁一般 3 到 5 个连接封顶。6. 从能跑到敢用参数化查询与上线前的自检6.1 把拼串换成 PreparedStatement示例里是纯查询看不出问题。一旦要做登录校验把用户输入直接拼进 SQL or 11这种输入就能绕过验证这在课程设计答辩时是会被当场问住的点。换成预编译语句参数走占位符输入里的引号不再参与 SQL 解析// ? 是占位符用户输入只作为值传入不参与 SQL 语法解析 String sql select uid from username where uid? and pwd?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, request.getParameter(uid)); // 参数下标从 1 开始 ps.setString(2, request.getParameter(pwd)); ResultSet rs ps.executeQuery(); boolean ok rs.next(); // 有记录即通过setString的下标从 1 起不是 0写错一位不报错但结果全错。预编译语句对 Access 的兼容性没问题桥驱动会把?转成 ODBC 的参数绑定性能上还省掉了重复解析 SQL 的开销。6.2 连接池与只读打开的取舍Access 是文件库连接池的意义和 MySQL 那种完全不同。池子里的连接长期不关.ldb锁文件就一直存在其他进程想写库就会被挡。我的做法是只读页面用连接池池大小 3有任何写操作的页面走短连接用完立刻关。写操作前先确认没有别的进程占着库比如你开着 Access 界面没关JSP 那边写就会失败报「操作必须使用一个可更新的查询」这个报错跟权限报错长得一样很容易查错方向。6.3 上线前的一张自检表检查项通过标准不通过的表现JDK 版本6 及以下或已换纯 Java 驱动ClassNotFoundExceptionODBC 驱动名与驱动程序页逐字一致未发现数据源名称位数JVM 与 ODBC 管理器同位数数据源配了但看不见文件路径getRealPath 返回值非 null路径解析失败目录权限运行账户可写能生成 .ldb找不到指定的文件编码页面、文件、JVM 三处一致中文显示为问号资源关闭close 全在 finally 里跑几天后连接超时这张表我每次部署老项目都会过一遍七项里通常能提前拦下五六个问题。那张表后来被我贴在工位显示器边上因为同一类错换台机器就会重来一次——尤其是位数和权限这两项看着最简单翻车率最高。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑