资讯动态

JSP连接ACCESS数据库:JDBC-ODBC桥驱动与Tomcat部署实战

发布时间:2026/10/16 21:17:53 来源:尧图企业网站定制
简介在Java Web开发中数据库连接是绕不开的基础技术JDBC作为标准接口为开发者提供了统一的访问方式。对于使用Access文件型数据库的场景JDBC-ODBC桥驱动曾是最经典的解决方案之一它通过ODBC层直接读取.mdb文件无需独立数据库服务适合轻量级数据展示与遗留系统维护。在高校课设、毕业设计或老旧系统迁移中这种连接方式依然有实用价值。本文从JSP环境下的数据库访问原理出发梳理了从路径定位、驱动加载、连接建立到结果集读取的完整链路并深入分析了JDK版本、ODBC位数、文件占用等典型踩坑点同时给出了参数化查询、配置外置等改造方向帮助开发者在维护旧项目或快速搭建演示系统时少走弯路。1. JSP连接ACCESS数据库一个.mdb文件放在对的位置一段连接串就能跑通的数据读取链路接到一个维护十几年前课程设计的活儿光是从旧Access库里把用户数据捞出来展示到网页上这件事就折腾了我一晚上。真正把「JSP连接ACCESS数据库」这条链路走通之后我才发现它比连MySQL简单得多不需要单独装数据库服务不用配账号密码一个.mdb文件放对位置几行JDBC代码把数据查出来。这个小项目就是把这条链路完整走了一遍建Access库和表、把文件部署到Tomcat的data目录、用JDBC-ODBC桥加载驱动、通过DriverManager建立连接、执行SQL并打印结果。适合两类人一是做课设毕设、手头只有Access且不想折腾MySQL的在校生二是在维护老系统、需要把mdb旧数据临时读出或迁移的开发者。2. 环境与落位Tomcat部署目录、mdb文件路径和字符集的三个前置准备2.1 版本组合怎么选JDK 7 Tomcat 6 Access 2003格式这套教程背后是一个很典型的年代组合。教程里示例路径是C:\Program Files\Apache Software Foundation\Tomcat 6.0说明它默认你用的是Tomcat 6.x那对应的JDK是6或7。为什么强调这个版本组合因为代码里Class.forName(sun.jdbc.odbc.JdbcOdbcDriver)加载的是JDK自带的JDBC-ODBC桥驱动这个类从JDK 8开始被官方移除。也就是说你用JDK 8甚至更高版本跑这段代码第一句就会抛ClassNotFoundException根本不是代码写错的问题而是驱动类在新时代的JDK里没了。数据库文件还有一个容易被忽略的点Access从2007版开始默认存成.accdb格式而老教程里的连接串写的是Driver{Microsoft Access Driver (*.mdb)}这个ODBC驱动只认早期格式。解决办法是把Access文件另存为「Access 2002-2003 格式(.mdb)」。我一般会建议在Access里做完表结构之后直接另存为.mdb文件名小写、纯英文避免后续在URL拼接这种环节被特殊字符坑到。2.2 数据库文件放哪里webapps\ROOT\data 与 getRealPath教程要求把test.mdb放到webapps\ROOT\data目录下。为什么不是随便丢一个磁盘路径关键在代码里的这一句String spath data/test.mdb; String dbpath application.getRealPath(spath);application.getRealPath()是JSP内置对象的方法作用是把一个相对于当前Web应用根目录的路径转换成服务器磁盘上的真实物理路径。Tomcat启动后webapps\ROOT就是根Web应用的根目录data/test.mdb经过转换就变成类似C:\Program Files\Apache Software Foundation\Tomcat 6.0\webapps\ROOT\data\test.mdb的完整路径。这种写法比硬编码一个C:\xxx\test.mdb要好换一台机器部署时只要安装目录变了硬编码路径必挂而用相对路径加getRealPath应用根目录内的相对关系不变路径就始终有效。要注意的是data文件夹默认不存在得在Tomcat的ROOT目录下手动新建别漏了这一步否则getRealPath能转出路径但文件不存在连接时会报找不到数据库文件。2.3 JSP文件保存编码gb2312还是UTF-8老代码第一行写的是contentTypetext/html; charsetgb2312这个选择符合当年Windows中文环境的习惯GB2312在小范围的简体中文场景下够用且兼容性好。但你用现代IDE比如较新的Eclipse、IDEA新建JSP时文件默认保存编码往往是UTF-8这会埋一个很隐蔽的坑文件实际字节是UTF-8页面指令声明是gb2312Tomcat按gb2312解码中文注释和输出的中文内容全变成乱码。我一般会做两件事第一把page指令改成charsetUTF-8同时保留meta标签也改成UTF-8第二确认IDE里文件右下角或设置里的编码确实是UTF-8再保存。如果你非要沿用gb2312那所有JSP文件必须统一按GBK/GB2312保存别混着来混编码比选错编码更难排查。顺带一提连接数据库时如果表里的中文数据乱码优先检查JSP文件编码和数据库字段排序规则跟JDBC连接串关系不大。3. 核心链路拆解从getRealPath到ResultSet的完整取数过程3.1 连接四要素路径、驱动类、URL和DriverManager整个JSP文件最核心的就是连接数据库这一段我按执行顺序拆开讲。先看完整代码% page contentTypetext/html; charsetUTF-8 languagejava importjava.sql.*% meta http-equivContent-Type contenttext/html; charsetUTF-8 % try { String spath data/test.mdb; // 相对Web应用根目录的数据库路径 String dbpath application.getRealPath(spath); // 转换成磁盘物理路径 String url jdbc:odbc:Driver{Microsoft Access Driver (*.mdb)};DBQ dbpath; Class.forName(sun.jdbc.odbc.JdbcOdbcDriver); // 加载JDBC-ODBC桥驱动 Connection conn DriverManager.getConnection(url); // 建立连接 String sql select * from username; // 查询全部用户 Statement stmt conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE); ResultSet rs stmt.executeQuery(sql); while (rs.next()) { out.print(用户名: rs.getString(uid)); out.print( 密码: rs.getString(pwd) br); } out.print(br恭喜你数据库连接成功); rs.close(); stmt.close(); conn.close(); } catch (Exception e) { out.print(数据库连接错误,错误信息如下br); out.print(e.getMessage()); } %最值得琢磨的是连接串这一行String url jdbc:odbc:Driver{Microsoft Access Driver (*.mdb)};DBQ dbpath;拆开看有三部分。jdbc:odbc:是协议前缀告诉DriverManager走JDBC-ODBC桥Driver{Microsoft Access Driver (*.mdb)}指定由ODBC加载哪个具体的Access驱动这里的驱动名对应Windows系统里ODBC数据源管理器能看到的名字DBQ后面跟的是数据库文件的物理路径这个参数表示Database Query File的来源路径。这里有个容易被新手误解的点这套写法不需要你去Windows「控制面板-管理工具-ODBC数据源」里手动建一个DSN数据源连接串里直接内联了驱动名和文件路径好处是部署时少一次系统配置坏处是URL一旦写入代码换驱动名或路径就得改源码。另外DriverManager.getConnection(url)用的是单参数重载因为Access默认没有用户名密码getConnection(url, , )这种三参数写法也能跑只是没必要。3.2 语句对象与结果集两个参数背后的性能含义Statement stmt conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);createStatement的两个参数很多人会原样抄但不清楚含义。第一个参数TYPE_SCROLL_SENSITIVE代表结果集可滚动且对数据库变化敏感也就是说rs.next()返回数据后你还能调用rs.previous()、rs.absolute(n)来回跳着看第二个参数CONCUR_UPDATABLE允许通过结果集直接更新数据库里的行比如rs.updateString(pwd, newpass)再rs.updateRow()。但当前场景只是把用户表打印出来这两个参数明显偏重。滚动游标和可更新结果集会占用更多数据库资源在Access这种文件型数据库上尤其明显。如果只是顺序查询我会写成Statement stmt conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);TYPE_FORWARD_ONLY表示游标只能向前移动CONCUR_READ_ONLY表示结果集只读这两种组合适合绝大多数报表展示场景性能更好且逻辑更简单。记住一个判断标准没有滚动和更新需求就别用重参数省下的资源会在数据量大时体现出来。接下来执行查询String sql select * from username; ResultSet rs stmt.executeQuery(sql); while (rs.next()) { out.print(用户名: rs.getString(uid)); out.print( 密码: rs.getString(pwd) br); }executeQuery只适用于select语句如果是insert、update、delete要用executeUpdate()。rs.next()每调用一次游标从当前位置向下移动一行返回true说明还有数据rs.getString(uid)按字段名取字符串值字段名必须和Access表里的列名完全一致大小写不敏感但拼写不能错。3.3 资源关闭顺序rs、stmt、conn一个都不能少代码末尾的关闭顺序是rs.close()→stmt.close()→conn.close()这个顺序是有讲究的。ResultSet依赖Statement执行产生Statement依赖Connection连接关闭时应从最上层的ResultSet开始逐级向下关最后关Connection。如果顺序反了先关Connection那么还活着的Statement和ResultSet会瞬间失去底层连接在部分驱动实现里会抛异常。更要命的是catch分支里的写法只打印错误信息没有关闭资源。一旦执行executeQuery时SQL出错后面的close三连全被跳过Connection就泄漏了Tomcat里的连接会被白白占用。JSP页面短时间访问看不出问题一旦并发上来连接池耗尽所有请求都会卡住。我一般会这样处理Connection conn null; Statement stmt null; ResultSet rs null; try { // ...连接和查询逻辑 } catch (Exception e) { out.print(数据库连接错误,错误信息如下br); out.print(e.getMessage()); } finally { if (rs ! null) { try { rs.close(); } catch (Exception e) {} } if (stmt ! null) { try { stmt.close(); } catch (Exception e) {} } if (conn ! null) { try { conn.close(); } catch (Exception e) {} } }finally块保证无论try里是否抛异常资源都会释放。如果你用的是JDK 7及以上还可以用try-with-resources语法声明在try括号里的Connection、Statement、ResultSet会在代码块结束后自动关闭连finally都不用写。这是一个值得养成的习惯数据库资源关闭这件事永远放在一定会执行的代码分支里。4. 踩坑与排查JDK版本、ODBC位数与路径玄学4.1 ClassNotFoundException: sun.jdbc.odbc.JdbcOdbcDriver现象Tomcat启动后访问JSP页面浏览器直接显示「数据库连接错误错误信息如下ClassNotFoundException: sun.jdbc.odbc.JdbcOdbcDriver」。原因JDK 8及以上版本将JDBC-ODBC桥驱动类从rt.jar中移除代码里的Class.forName找不到这个类。这个跟Tomcat版本无关纯粹是JDK版本导致的。解决要么把JDK降到7或6重新配置Tomcat的运行时环境要么升级数据库访问方案比如用Ucanaccess驱动替代JDBC-ODBC桥加载代码改成Class.forName(net.ucanaccess.jdbc.UcanaccessDriver)连接串改成jdbc:ucanaccess://物理路径。需要注意的是换了驱动之后连接串格式和驱动名都变了不是简单替换一行Class.forName就能跑通的。4.2 路径里出现空格或中文DBQ直接连不上现象代码逻辑完全一样但本机能连、服务器上连不上或者报「ODBC Microsoft Access 驱动程序登录失败。无法找到数据库文件」。原因DBQ后面的路径如果包含空格比如常见的C:\Program Files\ODBC驱动在解析时会把这个路径截断或混淆路径包含中文时更容易出错因为ODBC层对非ASCII字符的处理在不同Windows版本上表现不一致。解决把Tomcat安装到一个无空格的路径下比如D:\tomcatdata文件夹和.mdb文件名也保持纯英文小写。如果再不行可以在getRealPath返回的路径上做一次replace(\\, \\\\)转义或者在Tomcat层面调整URI编码但最省心的方案永远是让物理路径不出现空格和中文。4.3 64位系统上的驱动位数不匹配连接无响应现象同一套代码在一台64位Windows上能连另一台64位Windows上报「指定的DSN包含驱动程序和应用程序之间的体系结构不匹配」。原因老版本Office的Access驱动是32位的而Tomcat跑在64位JDK上时JVM是64位进程64位进程加载不了32位的ODBC驱动。这个属于经典的「驱动程序是32位但Java进程是64位」的位数打架问题肉眼看不到任何代码错误全在环境层面。解决让JVM位数和ODBC驱动位数对齐。最省事的做法是用32位JDK启动Tomcat或者下载安装64位的Access数据库引擎驱动前提是机器上没装32位Office因为新版驱动和旧版Office可能互斥。4.4 mdb文件被Access打开连接被锁定现象Access里开着这个数据库文件时JSP页面报「不能打开数据库。应用程序可能无法识别该数据库或文件可能已损坏。」但文件本身没坏。原因Access打开.mdb时会在同目录生成一个.ldb锁文件并独占文件句柄。Tomcat的JVM进程再去用ODBC驱动操作这个文件时拿不到足够的读写权限就会报文件占用错误。解决跑JSP之前先关闭Access里打开的所有对象确认.ldb锁文件已消失。如果只需要读取还可以给.mdb文件设置「只读」属性这样即使有人打开了Access查询操作也能正常执行但写入会受限对纯展示页面来说已经够用。4.5 表里字段名对不上SQL列名无效现象数据库连接成功但打印数据时报「列名无效」或「字段名未找到」可明明建表的时候写了uid和pwd。原因建表时字段名写成了ID、PASS等不同名称或者字段大小写与代码里rs.getString(uid)不完全一致。ODBC驱动对列名的解析在某些情况下是大小写敏感的拼写不一致就会报错。解决检查Access表设计视图里的字段列表保证代码里的字符串和表字段名称完全一致。更稳妥的做法是先执行一个getMetaData()把列名打印出来看看ResultSetMetaData meta rs.getMetaData(); for (int i 1; i meta.getColumnCount(); i) { out.print(meta.getColumnName(i) ); }这个技巧能把实际列名原样输出排除拼写错误避免对着代码猜。5. 二次开发改造参数化查询、配置外置与MySQL迁移拿到这份基础代码改造方向有三个按从易到难排序。第一个改造是把Statement换成PreparedStatement支持按条件查询String sql select * from username where uid ?; PreparedStatement ps conn.prepareStatement(sql); ps.setString(1, admin); // 第一个?号替换为admin ResultSet rs ps.executeQuery();setString(1, admin)是参数化绑定的写法第一个参数是占位符序号从1开始第二个参数是要传入的值。相比拼接SQL字符串这能彻底避开单引号注入问题这是最值得做的安全改造。第二个改造是把连接配置外置到属性文件避免每次改路径都要翻JSP源码# db.properties db.driversun.jdbc.odbc.JdbcOdbcDriver db.urljdbc:odbc:Driver{Microsoft Access Driver (*.mdb)};DBQ${dbpath}用一个简单的工具类加载属性文件再传给JDBC代码。这样换环境时只需改配置不用动页面逻辑。第三个改造是迁移到MySQL。把Class.forName换成com.mysql.cj.jdbc.DriverURL换成jdbc:mysql://localhost:3306/testdb?useUnicodetruecharacterEncodingutf8然后用工具把Access表结构和数据导入MySQL。迁移之后不再依赖Windows ODBC可以部署到Linux服务器上。我从第一次跑通这个教程到现在每次排查数据库连接问题都强制按同一个清单走驱动类在不在、连接串格式对不对、文件路径能不能被JDBC看到、资源关没关干净。这套查错顺序帮我少走了很多冤枉路。希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑