概览
整个过程分为三个主要步骤:
- 准备工作:获取并配置 SQL Server JDBC 驱动。
- 编写 Java 代码:使用 JDBC API 在 Java 中建立连接、执行查询并处理结果。
- 最佳实践与进阶:了解连接池、不同版本的驱动差异等重要概念。
第一步:准备工作
在编写 Java 代码之前,你必须确保你的开发环境已经准备好。
确保 SQL Server 服务正在运行
确保你的 SQL Server 实例(无论是本地还是远程)已经启动并且可以接受连接。
获取 JDBC 驱动程序
Java 应用程序需要一个 JDBC 驱动程序来与 SQL Server 通信,微软提供了官方的驱动程序。
-
推荐版本:Microsoft JDBC Driver 12.2 for SQL Server
- 这是目前最稳定和功能最全的版本,支持 Java 8 到 Java 17+。
- 下载地址:Microsoft JDBC Driver for SQL Server
-
旧版本:如果你使用的是非常旧的 Java 版本(如 Java 7),你可能需要下载
JDBC Driver 6.0或0版本。
将驱动程序 JAR 文件添加到项目中
下载完成后,你会得到一个 .zip 文件,解压它,在 mssql-jdbc-12.x.x.jre11.jar (或 jre8, jre17 等,根据你的 Java 版本选择) 文件就是核心的驱动库。
你需要将这个 JAR 文件添加到你的项目的类路径中。
如何添加(根据你的项目类型):
-
对于 Maven 项目(推荐) 这是最简单、最推荐的方式,你只需在
pom.xml文件中添加依赖即可,Maven 会自动帮你下载和管理驱动。<dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> <version>12.6.2.jre11</version> <!-- 请使用最新的版本号 --> </dependency> -
对于 Gradle 项目 在
build.gradle文件中添加:implementation 'com.microsoft.sqlserver:mssql-jdbc:12.6.2.jre11' // 请使用最新的版本号
-
对于普通 Java 项目(手动添加)
- 将下载的
.jar文件复制到你的项目的lib文件夹下(如果没有,就创建一个)。 - 在你的 IDE(如 IntelliJ IDEA 或 Eclipse)中,右键点击项目 -> Build Path / Project Structure -> Libraries。
- 点击 "Add External JARs..." 或 "Add JARs...",然后选择你刚刚复制到
lib文件夹下的 JAR 文件。
- 将下载的
第二步:编写 Java 代码
我们可以开始写代码了,下面是一个完整的示例,展示了如何连接到 SQL Server,执行一个简单的查询,并打印结果。
示例代码
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SqlServerConnector {
public static void main(String[] args) {
// --- 1. 定义连接信息 ---
// 请根据你的实际情况修改这些值
String dbUrl = "jdbc:sqlserver://localhost:1433;databaseName=YourDatabaseName;encrypt=false;trustServerCertificate=true;";
String dbUser = "your_username";
String dbPassword = "your_password";
// --- 2. 声明 JDBC 资源 ---
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// --- 3. 加载 JDBC 驱动 ---
// 对于 JDBC 4.0 (Java 6+) 及以上版本,这一步通常是可选的,
// 因为驱动会自动被加载,但显式写出可以确保代码清晰。
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// --- 4. 建立连接 ---
System.out.println("正在连接到数据库...");
conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
System.out.println("连接成功!");
// --- 5. 创建 Statement 对象 ---
stmt = conn.createStatement();
// --- 6. 执行 SQL 查询 ---
String sql = "SELECT id, name, email FROM YourTableName";
System.out.println("正在执行查询: " + sql);
rs = stmt.executeQuery(sql);
// --- 7. 处理结果集 ---
System.out.println("查询结果:");
while (rs.next()) {
// 通过列名获取数据,更安全且不易出错
int id = rs.getInt("id");
String name = rs.getString("name");
String email = rs.getString("email");
// 打印出每一行数据
System.out.println("ID: " + id + ", 姓名: " + name + ", 邮箱: " + email);
}
} catch (ClassNotFoundException e) {
System.err.println("找不到 JDBC 驱动类,请确保已将 JDBC 驱动 JAR 文件添加到类路径中。");
e.printStackTrace();
} catch (SQLException e) {
System.err.println("数据库连接或查询出错!");
e.printStackTrace();
} finally {
// --- 8. 关闭资源 (非常重要!) ---
// 使用 try-finally 块确保资源被关闭,即使发生异常
System.out.println("正在关闭资源...");
try {
if (rs != null) rs.close();
if (stmt != null) stmt.close();
if (conn != null) conn.close();
System.out.println("资源已关闭。");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
代码详解
-
连接字符串 (
dbUrl) 这是连接数据库的核心,格式如下:jdbc:sqlserver://[server_name][:port];[databaseName=your_db];[property1=value1];[property2=value2];jdbc:sqlserver://: 协议头,固定不变。localhost:1433: 服务器地址和端口。localhost表示本地,1433是 SQL Server 的默认端口,如果是远程服务器,请填入 IP 地址或域名。databaseName=YourDatabaseName: 你要连接的数据库的名称。encrypt=false;trustServerCertificate=true;: (非常重要) 这是在本地开发时常用的配置。encrypt=false: 不加密连接。trustServerCertificate=true: 信任服务器颁发的证书,即使它是由自签名机构签名的,这可以避免 SSL/TLS 证书验证错误,非常适合开发环境。在生产环境中,你应该使用有效的证书并正确配置encrypt=true和trustServerCertificate=false。
-
加载驱动 (
Class.forName) 这行代码显式地告诉 JVM 加载 SQL Server 的 JDBC 驱动类,它会初始化驱动程序,并向DriverManager注册自己,在现代 Java 版本中,这通常是自动完成的,但写上它是一种好习惯。 -
建立连接 (
DriverManager.getConnection) 这是使用驱动字符串、用户名和密码来建立实际数据库连接的方法,它会返回一个Connection对象,这是所有数据库操作的基础。 -
执行查询
conn.createStatement(): 创建一个Statement对象,用于执行静态 SQL 语句。stmt.executeQuery(sql): 执行一个查询,返回一个ResultSet对象,该对象包含了查询的结果集。
-
处理结果集 (
ResultSet)rs.next(): 将光标从当前位置向下移动一行,如果下一行存在,则返回true,否则返回false,通常在while循环中使用来遍历所有行。rs.getString("name"): 根据列名获取该行的值,使用列名比使用列索引(如rs.getString(1))更安全,因为即使 SQL 查询的列顺序改变,代码也不会出错。
-
关闭资源 (
finally块)Connection,Statement, 和ResultSet都是有限的系统资源(数据库连接),使用完毕后必须关闭它们,否则会导致资源泄漏。 最佳实践是:在finally块中关闭它们,这样无论try块是否抛出异常,资源都能被正确释放,关闭顺序应该是ResultSet->Statement->Connection。
第三步:最佳实践与进阶
使用 try-with-resources 语句 (Java 7+)
finally 块虽然能保证资源关闭,但代码略显冗长,从 Java 7 开始,推荐使用 try-with-resources 语句,它能自动实现资源的关闭。
// try-with-resources 会自动在 try 块结束后关闭实现了 AutoCloseable 接口的对象
try (Connection conn = DriverManager.getConnection(dbUrl, dbUser, dbPassword);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
// ... 在这里处理结果集 ...
while (rs.next()) {
// ...
}
} catch (SQLException e) {
// 处理异常
e.printStackTrace();
}
// conn, stmt, rs 会在这里自动关闭,无需在 finally 中手动关闭
这种方式更简洁、更安全,是现代 Java 编程的推荐做法。
使用连接池
在生产环境中,绝对不要在每次请求时都创建和销毁数据库连接。 这是一个非常耗费性能的操作。
解决方案是使用连接池,连接池在应用启动时预先创建一组数据库连接,并将它们保存在一个“池”中,当需要连接时,从池中获取一个用完后再放回池中,而不是关闭。
流行的连接池库:
- HikariCP: 目前性能最好的连接池,是 Spring Boot 2.x 的默认选择。
- Apache DBCP
- C3P0
使用 HikariCP 的示例:
添加 HikariCP 的 Maven 依赖:
<dependency>
<groupId>com.zaxxer</groupId>
<artifactId>HikariCP</artifactId>
<version>5.0.1</version> <!-- 使用最新版本 -->
</dependency>
修改你的代码:
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class SqlServerConnectorWithPool {
private static HikariDataSource dataSource;
// 在应用启动时初始化连接池
static {
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:sqlserver://localhost:1433;databaseName=YourDatabaseName;encrypt=false;trustServerCertificate=true;");
config.setUsername("your_username");
config.setPassword("your_password");
config.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
// 连接池配置 (可以根据需要调整)
config.setMaximumPoolSize(10); // 最大连接数
config.setMinimumIdle(5); // 最小空闲连接数
config.setConnectionTimeout(30000); // 连接超时时间 (毫秒)
dataSource = new HikariDataSource(config);
}
public static void main(String[] args) {
// 从连接池中获取一个连接
try (Connection conn = dataSource.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT id, name FROM YourTableName")) {
System.out.println("从连接池成功获取连接!");
while (rs.next()) {
System.out.println("ID: " + rs.getInt("id") + ", Name: " + rs.getString("name"));
}
} catch (SQLException e) {
e.printStackTrace();
}
// 连接会在 try-with-resources 结束时自动放回连接池,而不是关闭
}
}
不同 JDBC 驱动版本的差异
- JDBC Driver 4.0 (JAR: sqljdbc4.jar): 支持 JDBC 4.0 (Java 6)。
- JDBC Driver 6.0 (JAR: sqljdbc41.jar for Java 7, sqljdbc42.jar for Java 8): 支持更新的功能和 Java 版本。
- *JDBC Driver 7.0/8.0/9.0/12.2 (JAR: mssql-jdbc-.jar) 统一的驱动,支持 Java 8 到 Java 17+,功能更强大,性能更好,是当前唯一推荐**使用的版本。
注意:旧版本的驱动字符串可能略有不同,Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver") 在所有版本中都是一样的,但连接字符串的属性可能不同,请始终查阅你所使用版本的官方文档。
