一、数据库准备
(一)启用 TCP/IP 协议
-
操作入口
首先,我们要找到 SQL Server 配置管理器,操作路径为:通过 “此电脑” 右键选择 “管理”,在弹出的 “计算机管理” 窗口中,找到 “服务和应用程序”,点击展开后选择 “SQL Server 配置管理器”。或者我们可以直接搜索SQL Server 配置管理器,然后打开。 -
选择协议配置
在 “SQL Server 配置管理器” 中,依次展开 “SQL Server 网络配置”,然后选择对应你本机 SQL Server 的实例的协议(不同电脑可能安装了不同实例,要选择正确的那个)。在这里,我们重点关注 “TCP/IP 协议”。 -
启用协议(若被禁用)
如果 “TCP/IP 协议” 显示为已禁用状态(灰色图标),那么需要右键选中它,然后选择 “启用”,将其设置为已启用状态。之所以要这样做,是因为后续我们通过代码连接数据库时,需要通过 TCP/IP 协议来进行通信,若它处于禁用状态,数据库连接操作就会受到影响。 -
重启 SQL Server 服务
启用 “TCP/IP 协议” 后,还需要重新启动 SQL Server 服务来使这个配置生效。具体操作是:在 “SQL Server 配置管理器” 里面找到 “SQL Server 服务”,右键点击 “SqlServerAnalysisServices”(它一般显示为黄色图标),然后选择 “重新启动”,接下来耐心等待重启过程完成。 -
配置 TCP 端口
完成重启后,我们还需要对 TCP 端口进行配置。在 “SQL Server 网络配置” 中,再次双击刚才选择的 “TCP/IP 协议”,然后在弹出的窗口中切换到 “IP 地址” 选项卡,找到 “IPALL”(下拉到最后就能看到哦),在这里把 “TCP 端口” 的值改为 1433。这里要说明一下,1433 是 SQL Server 数据库的默认端口号,不过不同的数据库可能会有不同的默认端口号,所以要根据实际使用的数据库情况来确认端口号是否正确。
(二)设置数据库登录模式
-
进入登录名配置界面
打开你的 SQL Server 数据库实例(可以通过 SQL Server Management Studio 等工具打开哦),在实例中找到 “安全性” 选项,点击展开后选择 “登录名”,在这里能看到各种登录账号相关的配置信息。 -
配置 sa 登录名属性
右键点击 “sa” 这个登录名(它是 SQL Server 中常用的一个默认登录账号),然后选择 “属性”。在弹出的 “属性” 窗口中,勾选 “SQL Server 身份验证” 选项,并且设置好对应的密码(这里设置的密码要记,后面代码连接数据库时会用到)。 -
授予相关权限
配置好身份验证后,再切换到 “状态” 选项卡,在这里要分别授予 “连接到数据库引擎” 以及 “启用登录名” 这两项权限。虽然一般情况下默认就是这样配置的,但有时候在安装 SQL Server 数据库时可能设置了拒绝或者禁用相关的因素,所以我们查看并确保一下,这样才能保证最后的数据库连接能够成功。 -
服务器属性配置(安全性相关)
接着,右键点击数据库实例,选择打开 “服务器属性”,然后在弹出的窗口中切换到 “安全性” 选项卡,在这里按照实际需求进行相关配置(一般保持默认或者根据具体安全要求调整哦)。 -
重启数据库生效配置
完成上述登录模式相关的配置后,需要重启数据库来使这些配置生效。可以选择直接关闭数据库然后重新打开,或者右键点击服务器,选择 “重新启动数据库服务” 来完成重启操作。
(三)下载 SQL Server 驱动 jar 包
-
获取驱动包链接Download - JDBC Driver for SQL Server | Microsoft Learn这个是官网链接,大家可以下载最新版
-
选择合适驱动包版本
下载以后进行解压缩,你可以看到很多个jar文件
一系列文件有相关的操作文件指导
二、IDEA 准备
(一)导入 SQL Server 驱动 jar 包
-
进入项目结构设置
打开 IDEA 开发工具,在左上角找到 “Files” 菜单,点击展开后选择 “Project Structure” 选项,这会弹出 “Project Structure” 窗口,在这里可以对项目的各种结构和依赖进行配置。 -
添加库依赖
在 “Project Structure” 窗口中,切换到 “Libraries” 选项卡,然后点击 “ + ” 号(这个就是添加库的按钮啦),接着选择 “Java” 选项。这时候会弹出文件选择框,在这里选择刚刚下载的 SQL Server 驱动包所在的路径,最后点击 “OK” 按钮,这样就把 SQL Server 驱动 jar 包成功导入到项目中,它能帮助我们在代码里顺利连接 SQL Server 数据库。 - 可以自行选择导入的jar包,我这里选择的是mssql-jdbc-12.8.1.jre11.jar包
(二)编写测试代码
-
代码整体结构介绍
下面我们要编写测试代码啦,这段测试代码的功能是向 SQL Server 数据库发送 SQL 语句请求,并获取和处理返回的结果哦。以下的测试代码是建立在数据库中已经建立了名为 “test1” 的数据库,并且在里面创建了一张 “student” 表的基础上编写的,如果你的数据库环境不一样,需要根据实际情况进行调整。CREATE TABLE dbo.student (student_id INT PRIMARY KEY,name VARCHAR(50),gender VARCHAR(10),birth_date DATE,class_id INT );
INSERT INTO dbo.student (student_id, name, gender, birth_date, class_id) VALUES(101, '李军', '男', '1993-02-20', 1003),(103, '陆君', '男', '1991-06-01', 1001),(105, '匡明', '男', '1992-10-01', 1001),(107, '王丽', '女', '1993-01-20', 1003),(108, '曾华', '男', '1993-09-01', 1003),(109, '王芳', '女', '1992-02-10', 1001);
import java.sql.*;public class text {public static void main(String args[]) {// 修改数据库连接URL,添加trustServerCertificate=true来跳过证书验证(仅用于合适场景)String dbURL = "jdbc:sqlserver://localhost:1433;DatabaseName=test1;encrypt=true;trustServerCertificate=true";// 数据库用户名,替换为实际有效的用户名String userName = "sa";// 数据库密码,替换为实际对应的密码String userPwd = "abc";// SQL查询语句,这里示例为从student表查询学号、姓名、性别、班号,可按需修改String sql = "select student_id, name, gender, class_id from student";Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {// 加载驱动(在JDBC 4.0及以上通常不需要显式加载,但如果出现问题可尝试添加此句)Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");// 获取数据库连接connection = DriverManager.getConnection(dbURL, userName, userPwd);// 创建Statement对象用于执行SQL语句statement = connection.createStatement();// 执行查询语句,获取结果集resultSet = statement.executeQuery(sql);// 遍历结果集并输出数据while (resultSet.next()) {String student_id = resultSet.getString("student_id");String name = resultSet.getString("name");String gender = resultSet.getString("gender");String class_id = resultSet.getString("class_id");System.out.println("学号:" + student_id + " 姓名:" + name + " 性别:" + gender+ " 班号:" + class_id);}} catch (ClassNotFoundException e) {System.err.println("找不到数据库驱动类,请检查驱动是否添加到类路径中。");e.printStackTrace();} catch (SQLException e) {System.err.println("数据库操作出现异常,可能是连接、查询语句等问题。");e.printStackTrace();} finally {// 关闭资源,释放连接,遵循先开后关、后开先关的顺序try {if (resultSet!= null) {resultSet.close();}if (statement!= null) {statement.close();}if (connection!= null) {connection.close();}} catch (SQLException e) {System.err.println("关闭数据库资源时出现异常。");e.printStackTrace();}}}
}
上述为查询表格
-
在 IDEA 中,找到代码所在的类(这里是test 类),然后点击运行按钮就可以运行这段测试代码,看看是否能够成功连接数据库并获取到期望的数据。执行成功,说明连接成功。
下面为实现对表格的增删改查
import java.sql.*;public class text2 {// 数据库连接URL,添加了相关属性用于配置SSL连接(此处跳过证书验证,仅用于合适场景)private static final String dbURL = "jdbc:sqlserver://localhost:1433;DatabaseName=test1;encrypt=true;trustServerCertificate=true";// 数据库用户名,替换为实际有效的用户名private static final String userName = "sa";// 数据库密码,替换为实际对应的密码private static final String userPwd = "abc";public static void main(String args[]) {// 执行查询操作示例,先展示初始数据情况System.out.println("初始数据查询结果:");queryStudentData();// 插入数据操作示例(插入一条示例学生数据)int insertResult = insertStudent(110, "新同学", "男", 1005);if (insertResult > 0) {System.out.println("数据插入成功!");// 插入成功后再次查询数据,展示插入后的表格情况System.out.println("插入操作后数据查询结果:");queryStudentData();} else {System.out.println("数据插入失败!");}// 更新数据操作示例(更新刚插入的学生数据的姓名和班级信息)int updateResult = updateStudent(110, "更新后的同学", 1006);if (updateResult > 0) {System.out.println("数据更新成功!");// 更新成功后再次查询数据,展示更新后的表格情况System.out.println("更新操作后数据查询结果:");queryStudentData();} else {System.out.println("数据更新失败!");}// 删除数据操作示例(删除刚插入的学生数据)int deleteResult = deleteStudent(110);if (deleteResult > 0) {System.out.println("数据删除成功!");// 删除成功后再次查询数据,展示删除后的表格情况System.out.println("删除操作后数据查询结果:");queryStudentData();} else {System.out.println("数据删除失败!");}}// 查询学生数据方法public static void queryStudentData() {String sql = "select student_id, name, gender, class_id from student";Connection connection = null;Statement statement = null;ResultSet resultSet = null;try {Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");connection = DriverManager.getConnection(dbURL, userName, userPwd);statement = connection.createStatement();resultSet = statement.executeQuery(sql);while (resultSet.next()) {String student_id = resultSet.getString("student_id");String name = resultSet.getString("name");String gender = resultSet.getString("gender");String class_id = resultSet.getString("class_id");System.out.println("学号:" + student_id + " 姓名:" + name + " 性别:" + gender+ " 班号:" + class_id);}} catch (ClassNotFoundException e) {System.err.println("找不到数据库驱动类,请检查驱动是否添加到类路径中。");e.printStackTrace();} catch (SQLException e) {System.err.println("数据库操作出现异常,可能是连接、查询语句等问题。");e.printStackTrace();} finally {try {if (resultSet!= null) {resultSet.close();}if (statement!= null) {statement.close();}if (connection!= null) {connection.close();}} catch (SQLException e) {System.err.println("关闭数据库资源时出现异常。");e.printStackTrace();}}}// 插入学生数据方法public static int insertStudent(int studentId, String studentName, String studentGender, int studentClassId) {String sql = "INSERT INTO student (student_id, name, gender, class_id) VALUES (?,?,?,?)";Connection connection = null;PreparedStatement preparedStatement = null;int result = 0;try {Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");connection = DriverManager.getConnection(dbURL, userName, userPwd);// 使用预编译语句,提高性能并防止SQL注入preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1, studentId);preparedStatement.setString(2, studentName);preparedStatement.setString(3, studentGender);preparedStatement.setInt(4, studentClassId);result = preparedStatement.executeUpdate();} catch (ClassNotFoundException e) {System.err.println("找不到数据库驱动类,请检查驱动是否添加到类路径中。");e.printStackTrace();} catch (SQLException e) {System.err.println("数据库操作出现异常,可能是连接、查询语句等问题。");e.printStackTrace();} finally {try {if (preparedStatement!= null) {preparedStatement.close();}if (connection!= null) {connection.close();}} catch (SQLException e) {System.err.println("关闭数据库资源时出现异常。");e.printStackTrace();}}return result;}// 更新学生数据方法public static int updateStudent(int studentId, String newName, int newClassId) {String sql = "UPDATE student SET name =?, class_id =? WHERE student_id =?";Connection connection = null;PreparedStatement preparedStatement = null;int result = 0;try {Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");connection = DriverManager.getConnection(dbURL, userName, userPwd);preparedStatement = connection.prepareStatement(sql);preparedStatement.setString(1, newName);preparedStatement.setInt(2, newClassId);preparedStatement.setInt(3, studentId);result = preparedStatement.executeUpdate();} catch (ClassNotFoundException e) {System.err.println("找不到数据库驱动类,请检查驱动是否添加到类路径中。");e.printStackTrace();} catch (SQLException e) {System.err.println("数据库操作出现异常,可能是连接、查询语句等问题。");e.printStackTrace();} finally {try {if (preparedStatement!= null) {preparedStatement.close();}if (connection!= null) {connection.close();}} catch (SQLException e) {System.err.println("关闭数据库资源时出现异常。");e.printStackTrace();}}return result;}// 删除学生数据方法public static int deleteStudent(int studentId) {String sql = "DELETE FROM student WHERE student_id =?";Connection connection = null;PreparedStatement preparedStatement = null;int result = 0;try {Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");connection = DriverManager.getConnection(dbURL, userName, userPwd);preparedStatement = connection.prepareStatement(sql);preparedStatement.setInt(1, studentId);result = preparedStatement.executeUpdate();} catch (ClassNotFoundException e) {System.err.println("找不到数据库驱动类,请检查驱动是否添加到类路径中。");e.printStackTrace();} catch (SQLException e) {System.err.println("数据库操作出现异常,可能是连接、查询语句等问题。");e.printStackTrace();} finally {try {if (preparedStatement!= null) {preparedStatement.close();}if (connection!= null) {connection.close();}} catch (SQLException e) {System.err.println("关闭数据库资源时出现异常。");e.printStackTrace();}}return result;}
}
可以看到,我们在java中执行的命令SQL server 中的数据也会产生相应的变化。
三、问题排查
-
常见问题及排查方法
如果在运行代码过程中出现了问题,比如提示数据库连接失败之类的,可能有以下几种常见情况及对应的排查方法:
-
数据库连接相关问题:
- 首先检查前面数据库准备阶段的配置是否都正确完成了,比如 “TCP/IP 协议” 是否真的启用了,SQL Server 服务有没有正常重启,数据库登录的用户名和密码是否输入正确(要和前面配置的一模一样)等等。
- 查看 SQL Server 数据库实例是否正常运行,可以通过任务管理器或者 SQL Server 配置管理器里的 “SQL Server 服务” 查看对应的服务状态是否是 “正在运行” 哦。
- 检查数据库连接 URL 中的主机地址、端口号以及数据库名称是否准确无误,特别是如果你的数据库不是安装在本地主机或者使用了非默认端口号的情况。
-
驱动相关问题:
- 确认是否已经正确导入了 SQL Server 驱动 jar 包到项目中,在 IDEA 的 “Project Structure” 里的 “Libraries” 选项卡中查看一下驱动包是否存在且没有报错。
- 检查驱动包的版本是否与你的 SQL Server 数据库版本兼容,如果不兼容可能也会导致连接失败等问题,可以尝试更换为合适版本的驱动包重新测试一下。
-
代码逻辑及 SQL 语句问题:
- 检查测试代码里的 SQL 查询语句是否正确,比如表名是否拼写正确、列名是否存在、是否有语法错误等等,可以把查询语句拿到 SQL Server Management Studio 等数据库管理工具里先单独执行一下,看看是否能正常查询出数据。
- 如果代码在获取结果集数据或者其他逻辑处理部分出现异常,仔细查看代码逻辑,特别是按照列索引获取值的地方,如果表结构有变动可能就会出错,可以考虑修改成按列名获取结果集数据的方式来增强代码的健壮性。
-
常见错误1: SSL(安全套接字层)加密相关的配置和证书验证环节出现问题
配置连接 SQL Server 数据库时,将 “Encrypt” 属性设置为 “true”(意味着要使用 SSL 加密来建立安全连接),同时把 “trustServerCertificate” 属性设置为 “false”(表示不信任服务器自动提供的证书,需要进行严格的证书验证)。但在实际连接过程中,程序无法完成这个安全连接的建立,因为遇到了证书验证方面的阻碍。
- PKIX 路径构建失败(PKIX path building failed)
- 在 Java 中,基于 PKIX(公钥基础设施 X.509 标准)的证书验证机制用于确保通信对方(这里就是 SQL Server 服务器)的身份合法性以及建立安全的加密连接。
- 出现 “sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target” 这个异常,意味着 Java 程序在尝试构建从受信任的根证书到服务器提供证书的信任链(证书路径)时失败了。简单来说,就是它找不到一条有效的、能验证服务器证书合法性的信任路径。
- 通常原因是 Java 的信任存储库(truststore,存放受信任证书的地方)中没有包含能验证 SQL Server 服务器证书的相关证书,或者服务器证书的颁发链存在问题(比如中间证书缺失等情况)。
信任服务器证书(设置 trustServerCertificate 为 true)
- 如果你的环境允许,可以修改连接字符串中的 “trustServerCertificate” 属性为 “true”。这样做的话,Java 程序会跳过对服务器证书的严格验证流程,直接信任服务器提供的证书来建立加密连接。
String dbURL = "jdbc:sqlserver://localhost:1433;DatabaseName=text1;encrypt=true;trustServerCertificate=true";
- 导入服务器证书到 Java 信任存储库(truststore)
- 向 Java 的信任存储库(默认是
cacerts
文件)中导入 SQL Server 服务器的证书,使其成为受信任的证书。具体步骤如下:- 首先获取 SQL Server 服务器的证书。可以通过浏览器访问 SQL Server 所在的服务器地址(如果通过网络访问,例如
https://yourserveraddress:port
),然后从浏览器的证书查看选项中导出服务器证书(一般是.cer
格式)。 - 使用 Java 的
keytool
命令将导出的证书导入到cacerts
文件中。例如,假设证书文件名为sqlserver.cer
,默认密码是changeit
,命令如下:
- 首先获取 SQL Server 服务器的证书。可以通过浏览器访问 SQL Server 所在的服务器地址(如果通过网络访问,例如
- 向 Java 的信任存储库(默认是
keytool -import -alias sqlserver -file sqlserver.cer -keystore $JAVA_HOME/jre/lib/security/cacerts -storepass changeit
完成导入后,再尝试运行你的 Java 程序,此时 Java 应该就能基于正确的证书验证构建 PKIX 路径,从而成功建立 SSL 加密的数据库连接。