Java 访 问 SQL Server 数 据 库 的 设 计 与 实 现 Zhuojun Zhao 数 据 库 连 接 是 软 件 项 目 开 发 中 很 重 要 的 一 个 环 节, 但 是 很 多 Java 初 学 者 在 学 习 连 接 数 据 库 的 过 程 中 感 到 非 常 头 疼, 总 是 出 现 一 系 列 的 问 题, 不 是 连 接 错 误 报 异 常, 就 是 无 法 显 示 数 据 库 表 中 的 数 据, 或 者 修 改 和 删 除 数 据 不 成 功 本 文 是 笔 者 根 据 多 年 Java 教 学 经 验, 对 Java 访 问 SQL Server 数 据 库 的 三 种 方 式 : JDBC-ODBC 桥 连 接 纯 Java 方 式 连 接 和 WebLogic 数 据 库 连 接 池 连 接 进 行 归 纳 总 结, 对 常 见 的 问 题 给 出 最 佳 的 解 决 的 办 法, 并 给 出 了 详 尽 的 配 置 步 骤 和 数 据 库 连 接 源 代 码 和 注 释 Java 语 言 连 接 数 据 库 主 要 采 用 JDBC(Java Database Connectivity) 技 术, 它 是 Sun 提 供 的 一 套 数 据 库 编 程 接 口 API 函 数 的 总 称, 由 Java 语 言 编 写 的 类 组 成 用 JDBC 写 的 程 序 能 够 自 动 地 将 SQL 语 句 传 送 给 相 应 的 数 据 库 管 理 系 统 不 但 如 此, 使 用 Java 编 写 的 应 用 程 序 可 以 在 任 何 支 持 Java 的 平 台 上 运 行, 不 必 在 不 同 的 平 台 上 编 写 不 同 的 应 用 Java 和 JDBC 的 结 合 可 以 让 开 发 人 员 在 开 发 数 据 库 应 用 程 序 时 真 正 实 现 Write Once,Run Everywhere! JDBC 访 问 数 据 库 的 可 以 如 图 一 所 示 : Java 应 用 程 序 JDBC SQL 命 令 结 果 数 据 库 图 一 :JDBC 访 问 数 据 库 示 意 图 下 面 本 文 就 Java 语 言 使 用 JDBC 技 术 访 问 SQLServer 数 据 库 的 三 种 方 式 : JDBC-ODBC 桥 连 接 纯 Java 方 式 连 接 和 WebLogic 数 据 库 连 接 池 连 接 进 行 详 细 介 绍 本 文 假 设 以 下 要 访 问 的 SQLServer 数 据 库 的 名 称 是 StudentDB, 而 表 的 名 称 是 Student 一 JDBC-ODBC 桥 连 接 方 式 JDBC-ODBC 桥 连 接 方 式 的 第 一 步 是 创 建 数 据 源, 然 后 再 在 Java 工 程 里 写 访 问 数 据 库 的 代 码 1 建 立 数 据 源 点 击 控 制 面 板 管 理 工 具 数 据 源 (ODBC) 打 开 ODBC 数 据 源 管 理 器 对 话 框, 也 可 以 在 开 始 运 行 里 键 入 命 令 :odbcad32 打 开 ODBC 数 据 源 管 理 器 对 话 框 点 击 对 话 框 里 的 添 加 按 钮 打 开 创 建 新 数 据 源 对 话 框, 拉 动 滚 动 条 选 择 最 后 的 SQL Server 驱 动 程 序, 打 开 创 建 SQL Server 新 数 据 源 对 话 框, 输 入 数 据 源 的 名 称 mysql ( 请 记 住 该 数 据 源 的 名 称 ), 服 务 器 输 入., 然 后 点 击 下 一
步, 选 择 使 用 用 户 输 入 登 录 ID 和 密 码 的 SQL Server 身 份 验 证, 并 输 入 用 户 名 sa, 以 及 密 码, 如 果 没 有 则 不 输 入, 再 点 击 下 一 步, 在 上 面 的 更 改 默 认 的 数 据 库 输 入 框 里, 选 择 StudentDB( 我 们 前 面 假 设 的 数 据 库 ), 然 后 一 直 点 击 下 一 步 直 到 完 成 在 这 一 步 里, 特 别 提 醒 读 者 最 可 能 遇 到 的 错 误 有 以 下 几 个 : [Microsoft][ODBC SQL Server Driver][DBNETLIB]SQL Server 不 存 在 或 访 问 被 拒 绝 解 决 方 案 : 检 查 一 下 你 的 SQL Server 服 务 器 是 否 没 有 启 动 或 连 接 断 开 [Microsoft][ODBC SQL Server Driver][SQL Server] 无 法 打 开 登 录 'StudentDB' 中 请 求 的 数 据 库 登 录 失 败 解 决 方 案 : 可 能 是 忘 记 将 要 连 接 的 数 据 库 附 加 到 SQL Server 服 务 器 上 [Microsoft][ODBC SQL Server Driver][SQL Server] 对 象 名 'Student' 无 效 解 决 方 案 : 忘 记 更 改 默 认 的 数 据 库, 系 统 默 认 的 数 据 库 是 master, 这 里 一 定 要 更 改 为 自 己 要 连 接 的 数 据 库 StudentDB 2 在 工 程 里 访 问 数 据 库 很 多 初 学 者 一 开 始 写 连 接 数 据 库 的 代 码 是 哪 里 需 要 就 在 哪 写 代 码, 造 成 代 码 混 乱, 一 个 修 改 会 导 致 多 次 修 改, 代 码 维 护 非 常 困 难 建 议 连 接 和 访 问 数 据 库 的 代 码 应 该 单 独 写 到 一 个 类 中, 在 该 类 中 可 以 分 别 写 以 下 几 个 方 法 : 连 接 数 据 库 的 方 法 获 得 数 据 库 数 据 的 方 法 更 新 数 据 库 数 据 的 方 法 源 代 码 如 下 : import java.sql.*; public class DBCon { //JDBC-ODBC 桥 连 接 数 据 库 方 法 public static Connection JdbcOdbcCon(){ // 加 载 数 据 库 驱 动 程 序 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver"); // 创 建 数 据 库 连 接 Connection conn=drivermanager.getconnection("jdbc:odbc:mysql","sa",""); // 返 回 连 接 对 象 return conn; catch(exception ex){ ex.printstacktrace(); return null; // 获 得 数 据 库 数 据 的 方 法 public static void getinfo(string sql) throws Exception{ Connection conn=jdbcodbccon(); Statement stmt=null; ResultSet rs=null; // 创 建 会 话 stmt=conn.createstatement(); // 执 行 查 询, 获 得 结 果 集 rs=stmt.executequery(sql); // 获 得 表 中 字 段 的 个 数
ResultSetMetaData rsmd=rs.getmetadata(); int count=rsmd.getcolumncount(); // 打 印 System.out.print(" 学 号 \t 姓 名 \t 性 别 \n"); System.out.println("====================="); // 显 示 结 果 集 的 内 容 while(rs.next()){ for(int i=1;i<=count;i++){ System.out.print(rs.getString(i)+"\t"); System.out.print("\n"); finally{ // 关 闭 连 接 if(rs!=null) rs.close(); if(stmt!=null) stmt.close(); if(conn!=null) conn.close(); // 更 新 数 据 库 数 据 的 方 法 public static void updateinfo(string sql) throws Exception{ Connection conn=jdbcodbccon(); Statement stmt=null; // 创 建 会 话 stmt=conn.createstatement(); // 执 行 查 询 stmt.executeupdate(sql); finally{ // 关 闭 连 接 if(stmt!=null) stmt.close(); if(conn!=null) conn.close(); 在 JDBC-ODBC 桥 连 接 的 方 式 中, 最 容 易 出 错 的 地 方 有 以 下 几 点 : java.lang.classnotfoundexception 解 决 方 案 : 将 连 接 字 符 串 sun.jdbc.odbc.jdbcodbcdriver 写 错, 这 串 连 接 字 符 串 一 点 都 不 能 写 错, 包 括 大 小 写 都 不 能 错 java.sql.sqlexception: [Microsoft][ODBC 驱 动 程 序 管 理 器 ] 未 发 现 数 据 源 名 称 并 且 未 指 定 默 认 驱 动 程 序 解 决 方 案 : 检 查 数 据 源 的 名 称 是 否 正 确, 或 数 据 源 是 否 已 经 创 建, java.sql.sqlexception: [Microsoft][ODBC SQL Server Driver][SQL Server] 用 户 '(null)' 登 录 失 败 原 因 : 未 与 信 任 SQL Server 连 接 相 关 联 解 决 方 案 :Connection conn=drivermanager.getconnection("jdbc:odbc:mysql","sa",""); 这 句 里 的 用 户 名 sa 和 密 码 不 要 省 略 java.sql.sqlexception: [Microsoft][ODBC SQL Server Driver][SQL Server] 用 户 'sa' 登 录 失 败 原 因 : 未 与 信 任 SQL Server 连 接 相 关 联 解 决 方 案 : 这 个 错 误 和 上 面 那 条 错 误 很 相 似, 但 是 是 用 户 sa 登 录 不 成 功 这 很 可 能 是 你 的 SQLServer 服 务 器 只 允 许 用 Windows 身 份 验 证 在 SQL Server2000 企 业 管 理 器 的 左 边 树 形 节 点 上 选 择 你 SQL Server 服 务 器, 鼠 标 右 键 打 开 属 性 对 话 框, 选 择 安 全 性 选 项 卡, 然 后 在 身 份 验 证 选 择 SQL Server
和 Windows 身 份 验 证 即 可 但 是 需 要 重 启 SQL Server 服 务 器 才 生 效 二 纯 Java 连 接 方 式 纯 Java 方 式 连 接 和 JDBC-ODBC 桥 连 接 不 同 之 处 有 三 点 : 纯 Java 方 式 连 接 不 需 要 建 立 数 据 源, 纯 Java 方 式 连 接 数 据 库 连 接 字 符 串 不 同 于 JDBC-ODBC 桥 连 接 字 符 串 JDBC-ODBC 桥 连 接 字 符 串 :sun.jdbc.odbc.jdbcodbcdriver 纯 Java 方 式 连 接 连 接 字 符 串 :com.microsoft.jdbc.sqlserver.sqlserverdriver 纯 Java 方 式 连 接 的 URL 和 JDBC-ODBC 桥 连 接 的 URL 不 同 JDBC-ODBC 桥 连 接 URL:jdbc:odbc: 数 据 源 纯 Java 方 式 连 接 连 接 URL: jdbc:microsoft:sqlserver://localhost:1433;databasename= 数 据 库 名 SQLServer2000 数 据 库 必 须 打 SP3 以 上 的 补 丁 需 要 SQLServer2000 的 驱 动 程 序 的 三 个 jar 文 件 以 下 是 纯 Java 方 式 连 接 SQLServer2000 数 据 库 方 法 : // 纯 Java 方 式 连 接 SQLServer2000 数 据 库 方 法 public static Connection JavaCon(){ // 加 载 数 据 库 驱 动 程 序 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver"); // 创 建 数 据 库 连 接 String url="jdbc:microsoft:sqlserver://localhost:1433;databasename=studentdb"; Connection conn=drivermanager.getconnection(url,"sa",""); // 返 回 连 接 对 象 return conn; catch(exception ex){ ex.printstacktrace(); return null; 纯 Java 方 式 连 接 数 据 库 需 要 的 驱 动 程 序 msbase.jar mssqlserver.jar msutil.jar 三 个 jar 文 件 可 以 从 CSDN 网 址 :http://download.csdn.net/source/404206 或 微 软 官 方 网 站 http://download.microsoft.com/download/3/0/f/30ff65d3-a84b-4b8a-a570-27366b2271d8/setup.exe 上 免 费 下 载 下 面 就 JBuilder2005 和 Eclipse 工 程 里 如 何 配 置 这 三 个 驱 动 程 序 分 别 进 行 讲 解 : JBuilder2005 里 配 置 驱 动 程 序 有 两 个 步 骤 : 创 建 库 文 件 : 在 菜 单 里 选 择 Tools Configure Libraries, 打 开 Configure Libraries ( 配 置 库 文 件 ) 对 话 框, 点 击 New 按 钮, 在 New Library Wizard ( 新 建 库 文 件 向 导 ) 对 话 框 的 Name 输 入 框 输 入 自 己 命 名 的 名 称, 在 下 面 的 Location 输 入 框 选 择 Project( 这 是 为 了 把 该 库 文 件 保 存 在 该 工 程 里, 这 样 以 后 就 不 用 再 次 配 置 了 ) 点 击 Add 按 钮, 在 弹 出 的 Select One or More Directories 对 话 框 里 浏 览 到 三 个 驱 动 程 序 jar 文 件, 选 中 后 按 下 OK 按 钮 配 置 库 文 件 : 在 菜 单 里 选 择 Project Project Properties, 选 择 Required Libraries 选 项 卡, 点 击 Add 按 钮 打 开 Add to Project Classpath 对 话 框 里, 选 择 Project 的 节 点 下 你 刚 刚 建 好 的 库 文 件, 选 中 后 按 下 OK 按 钮
Eclipse 里 配 置 驱 动 程 序 只 有 一 步 : 在 菜 单 里 选 择 Project Properties, 打 开 Project Properties 对 话 框, 在 左 边 选 择 Java Build Path, 然 后 点 击 Libraries 选 项 卡, 点 击 Add External JARs 按 钮 打 开 JAR Selection 对 话 框 里, 浏 览 选 择 三 个 驱 动 程 序 jar 文 件, 选 中 后 按 下 打 开 按 钮 纯 Java 方 式 连 接 SQLServer2000 最 容 易 出 现 以 下 错 误 : java.sql.sqlexception: [Microsoft][SQLServer 2000 Driver for JDBC]Error establishing socket 解 决 方 案 : 检 查 你 的 SQLServer2000 是 否 打 了 SP3 以 上 的 补 丁, 或 者 是 否 把 URL 里 的 端 口 号 写 错 了 常 用 的 端 口 号 是 1433, 但 也 可 能 端 口 号 1433 被 占 用 后, 改 用 了 别 的 端 口 号 你 可 以 用 以 下 方 法 查 到 你 的 SQLServer2000 占 用 的 端 口 号 : 在 SQL Server2000 企 业 管 理 器 的 左 边 树 形 节 点 上 选 择 你 SQL Server 服 务 器, 鼠 标 右 键 打 开 属 性 对 话 框, 点 击 下 面 的 网 络 配 置 按 钮, 在 打 开 的 SQLServer 网 络 实 用 工 具 对 话 框 里 的 右 边 选 择 TCP/IP, 然 后 点 击 下 面 的 属 性, 便 可 以 看 到 占 用 的 端 口 号 用 JDBC-ODBC 桥 连 接 方 式 访 问 SQLServer2005 数 据 库 和 访 问 SQLServer2000 数 据 库 一 样, 这 里 就 不 再 重 述 纯 Java 方 式 访 问 SQLServer2005 数 据 库 的 步 骤 和 SQLServer2000 一 样, 但 是 连 接 字 符 串 不 相 同, 下 面 是 纯 Java 方 式 连 接 SQLServer2005 数 据 库 的 代 码 ( 注 意 : 连 接 SQLServer2005 连 接 字 符 串 和 URL 与 连 接 SQLServer2000 的 不 同 ): // 纯 Java 连 接 SQLServer2005 数 据 库 方 法 public static Connection JavaCon2005(){ // 加 载 数 据 库 驱 动 程 序 Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); // 创 建 数 据 库 连 接 String url="jdbc:sqlserver://localhost:1433;databasename=studentdb"; Connection conn=drivermanager.getconnection(url,"sa",""); // 返 回 连 接 对 象 return conn; catch(exception ex){ ex.printstacktrace(); return null; 使 用 纯 Java 方 式 连 接 SQLServer2005 数 据 库 时 不 需 要 像 访 问 SQLServer2000 数 据 库 那 样 要 打 SP3 以 上 的 补 丁 纯 Java 方 式 连 接 SQLServer2005 数 据 库 的 驱 动 程 序 sqljdbc.jar 文 件 可 以 从 CSDN 网 址 : http://download.csdn.net/source/602592( 资 源 分 : 2 分 ) 或 微 软 官 方 网 址 http://msdn.microsoft.com/zh-cn/data/aa937724(en-us).aspx 上 免 费 下 载 该 驱 动 程 序 jar 文 件 在 JBuilder2005 和 Eclipse 工 程 里 的 配 置 同 SQLServer2000 一 样 三 WebLogic 数 据 库 连 接 池 访 问 SQLServer 数 据 库 WebLogic 数 据 库 连 接 池 访 问 数 据 库 的 方 式 必 须 首 先 创 建 WebLogic 数 据 库 连 接 池, 然 后 配 置 需 要 的 jar 文 件, 最 后 再 在 Java 程 序 里 写 连 接 代 码
1 创 建 数 据 库 连 接 池 启 动 WebLogic 服 务 器, 然 后 登 录 WebLogic 服 务 器 的 控 制 台, 在 左 边 的 树 形 菜 单 上 选 择 Services JDBC Data Sources, 在 左 边 的 上 边 点 击 Lock & Edit 按 钮, 点 击 New 按 钮 进 入 Create a New JDBC Data Source 面 板, 在 Create a New JDBC Data Source 面 板 里, 在 Name 输 入 框 里 键 入 自 己 命 名 的 数 据 库 连 接 池 名 称, 在 JNDI Name 输 入 框 里 键 入 JNDI 资 源 名 称, 这 两 个 名 称 可 以 相 同,Database Type( 数 据 库 类 型 ) 选 择 MS SQL Server,Database Driver( 数 据 库 驱 动 程 序 ) 选 择 Microsoft s MS SQL Server(Type 4)Versions:2000,2005 点 击 Next 按 钮, 再 该 画 面 里 选 择 One-Phase Commit, 再 点 击 Next, 在 Database Name 输 入 框 里 键 入 数 据 库 名 StudentDB, 在 Host Name 输 入 框 里 键 入 localhost, Port 输 入 框 里 键 入 端 口 号 1433, Database User Name 输 入 框 里 键 入 sa, 如 果 有 数 据 库 登 录 密 码, 则 输 入 两 次 密 码, 如 果 没 有 则 不 用 输 入, 在 Test Table Name 输 入 框 里 键 入 表 名 Student, 然 后 点 击 Test Configuration 测 试 连 接, 如 果 显 示 Connection Test Success 提 示, 则 说 明 连 接 成 功 点 击 Next 按 钮, 勾 选 AdminServer, 在 点 击 Finish 按 钮 完 成 创 建 数 据 库 连 接 在 左 上 角, 点 击 绿 色 Activate Changes 按 钮 保 存 配 置 这 里 特 别 提 醒 读 者 的 是, 创 建 连 接 SQLServer2000 的 WebLogic 数 据 库 连 接 池 也 必 须 对 SQLServer2000 打 SP3 以 上 的 补 丁, 因 为 WebLogic 数 据 库 连 接 池 也 是 纯 Java 方 式 连 接 的 2 配 置 需 要 的 jar 文 件 在 Eclipse 工 程 里, 需 要 配 置 使 用 WebLogic 服 务 器 资 源 的 jar 文 件 以 及 SQLServer2000 数 据 库 驱 动 程 序 的 三 个 jar 文 件 配 置 weblogic.jar 文 件 : 在 菜 单 里 选 择 Project Properties, 打 开 Project Properties 对 话 框, 在 左 边 选 择 Java Build Path, 然 后 点 击 Libraries 选 项 卡, 点 击 Add External JARs 按 钮 打 开 JAR Selection 对 话 框 里, 浏 览 WebLogic 服 务 器 安 装 文 件 夹 bea\wlserver_10.0\server\lib 里 选 择 weblogic.jar 文 件, 选 中 后 按 下 打 开 按 钮 配 置 连 接 SQLServer2000 的 三 个 jar 文 件 : 在 菜 单 里 选 择 Project Properties, 打 开 Project Properties 对 话 框, 在 左 边 选 择 Java Build Path, 然 后 点 击 Libraries 选 项 卡, 点 击 Add External JARs 按 钮 打 开 JAR Selection 对 话 框 里, 浏 览 选 择 三 个 驱 动 程 序 jar 文 件, 选 中 后 按 下 打 开 按 钮 值 得 注 意 的 是 最 好 先 配 置 weblogic.jar 文 件, 再 配 置 连 接 SQLServer2000 的 三 个 jar 文 件 配 置 顺 序 的 不 同 有 可 能 导 致 数 据 库 连 接 出 现 问 题 3 在 Eclispe 工 程 中 的 Java 程 序 里 写 连 接 代 码 在 Eclispe 工 程 里 新 建 一 个 类, 并 写 下 如 下 的 连 接 代 码 : // 导 入 所 需 的 包 import javax.naming.*; import javax.sql.*; import java.sql.*;
import java.util.*; public class WebLogicDemo { public static void main(string[] args) { // 实 例 化 属 性 Properties p=new Properties(); // 指 定 服 务 器 为 WebLogic p.put(context.initial_context_factory, "weblogic.jndi.wlinitialcontextfactory"); // 指 定 URL 地 址 p.put(context.provider_url, "t3://localhost:7001"); // 获 得 上 下 文 环 境 的 对 象 Context ctx=new InitialContext(p); // 从 JNDI 书 上 获 得 数 据 库 连 接 池 资 源 得 到 数 据 源 DataSource ds=(datasource)ctx.lookup("mysql"); // 根 据 数 据 源 创 建 数 据 库 连 接 Connection conn=ds.getconnection(); // 创 建 会 话 Statement stmt=conn.createstatement(); // 写 SQL 语 句 String sql="select * from Student"; // 执 行 查 询 ResultSet rs=stmt.executequery(sql); // 输 出 查 询 的 结 果 System.out.println(" 学 号 姓 名 性 别 "); while(rs.next()){ System.out.print(rs.getString(1)+"\t"); System.out.print(rs.getString(2)+"\t"); System.out.println(rs.getString(3)); // 关 闭 rs.close(); stmt.close(); conn.close(); catch(exception ex){ ex.printstacktrace(); WebLogic 数 据 库 连 接 池 连 接 SQLServer 数 据 库 方 式 最 容 易 出 现 以 下 错 误 : javax.naming.namenotfoundexception: Unable to resolve 'mysql'. Resolved '' [Root exception is javax.naming.namenotfoundexception: 解 决 方 案 :JNDI 树 上 没 有 名 叫 mysql 的 资 源, 是 不 是 没 有 在 WebLogic 上 创 建 数 据 库 连 接 池, 或 者 连 接 池 的 名 称 不 叫 mysql javax.naming.noinitialcontextexception: Cannot instantiate class: weblogic.jndi.wlinitialcontextfactory [Root exception is java.lang.classnotfoundexception: weblogic.jndi.wlinitialcontextfactory] 解 决 方 案 :weblogic.jar 文 件 没 有 配 置, 请 配 置 weblogic.jar 文 件 javax.naming.communicationexception [Root exception is java.net.connectexception: t3://localhost:7001: Destination unreachable 解 决 方 案 :Weblogic 服 务 器 没 有 正 常 启 动, 启 动 WebLogic 服 务 器
如 果 用 WebLogic 数 据 库 连 接 池 方 式 连 接 SQLServer2005 数 据 库, 则 不 需 要 打 SP3 以 上 的 补 丁, 但 是 在 选 择 Database Driver( 数 据 库 驱 动 程 序 ) 选 择 Microsoft s MS SQL Server(Type 4)Versions: 2005, 并 在 Eclipse 里 配 置 SQLServer2005 的 驱 动 程 序 sqljdbc.jar 文 件 以 上 三 种 连 接 数 据 库 的 方 式 比 较 常 用, 前 面 两 种 一 般 用 于 C/S 架 构 的 应 用 程 序, 而 最 后 的 WebLogic 数 据 库 连 接 池 方 式 则 适 用 于 大 型 的 B/S 架 构 应 用 程 序, 效 率 较 高 读 者 可 根 据 需 要 选 用 适 合 的 数 据 库 连 接 方 式