Microsoft JDBC Driver 版本對應表
| 驅動版本 | JAR 檔名 | 支援 JDK | 支援 SQL Server | 備註 |
| 12.4+ (最新) | mssql-jdbc-12.4.x.jre11/17/21.jar | 11, 17, 21 | 2008 - 2022 | 模組化、Jakarta EE 9+ |
| 11.2 | mssql-jdbc-11.2.x.jre8/11/17.jar | 8, 11, 17 | 2008 - 2019 | 長期支援版 |
| 10.2 | mssql-jdbc-10.2.x.jre8/11.jar | 8, 11 | 2008 - 2019 | JDK 8 專案常用 |
| 舊版 (停維護) | sqljdbc4.jar / sqljdbc41.jar | 6, 7, 8 | 2008 - 2014 | 不建議新專案使用 |
Maven 依賴配置 (推薦)
com.microsoft.sqlserver
mssql-jdbc
12.4.2.jre11
com.microsoft.sqlserver
mssql-jdbc
11.2.3.jre8
SQL Server 端必要配置
- 啟用 TCP/IP 協議:
- SQL Server Configuration Manager → SQL Server Network Configuration → Protocols for MSSQLSERVER
- 右鍵 TCP/IP → Enable
- IP Addresses 頁籤 → IPAll → TCP Port 設為 1433
- 啟用 SQL Server Authentication:
- SSMS 連線 → 伺服器屬性 → Security → SQL Server and Windows Authentication mode
- 重啟 SQL Server 服務生效
- 防火牆開放 1433 埠 (Windows 防火牆/雲安全組)
- 建立資料庫與登入帳號:
CREATE DATABASE MyDB;
CREATE LOGIN app_user WITH PASSWORD = 'StrongP@ssw0rd';
USE MyDB;
CREATE USER app_user FOR LOGIN app_user;
ALTER ROLE db_owner ADD MEMBER app_user;
連線字串完整參數詳解
# 基礎連線 (不驗證憑證,開發適用)
jdbc:sqlserver://localhost:1433;databaseName=MyDB;encrypt=true;trustServerCertificate=true
# 生產環境 (驗證憑證)
jdbc:sqlserver://prod-db:1433;databaseName=MyDB;encrypt=true;trustServerCertificate=false;hostNameInCertificate=prod-db.example.com
# 完整參數範例
jdbc:sqlserver://host:1433
;databaseName=MyDB
;user=app_user
;password=StrongP@ssw0rd
;encrypt=true
;trustServerCertificate=true
;loginTimeout=30
;socketTimeout=30
;applicationName=MyApp
;sendStringParametersAsUnicode=true
;selectMethod=cursor
Spring Boot 整合配置
application.yml
spring:
datasource:
url: jdbc:sqlserver://localhost:1433;databaseName=MyDB;encrypt=true;trustServerCertificate=true
username: app_user
password: StrongP@ssw0rd
driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver
hikari:
maximum-pool-size: 20
minimum-idle: 5
connection-timeout: 30000
idle-timeout: 600000
max-lifetime: 1800000
connection-test-query: SELECT 1
initialization-fail-timeout: 0
jpa:
database-platform: org.hibernate.dialect.SQLServerDialect
hibernate:
ddl-auto: validate
show-sql: false
properties:
hibernate:
format_sql: true
jdbc:
batch_size: 50
fetch_size: 100
多資料源配置範例
@Configuration
@MapperScan(basePackages = "com.app.mapper.db1", sqlSessionFactoryRef = "db1SqlSessionFactory")
public class Db1Config {
@Bean @ConfigurationProperties("spring.datasource.db1")
DataSource db1DataSource() { return DataSourceBuilder.create().build(); }
@Bean SqlSessionFactory db1SqlSessionFactory(@Qualifier("db1DataSource") DataSource ds) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(ds);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/db1/*.xml"));
return bean.getObject();
}
@Bean DataSourceTransactionManager db1TxManager(@Qualifier("db1DataSource") DataSource ds) {
return new DataSourceTransactionManager(ds);
}
}
原生 JDBC 連線測試代碼
import java.sql.*;
public class SqlServerConnectionTest {
public static void main(String[] args) {
String url = "jdbc:sqlserver://localhost:1433;databaseName=MyDB;encrypt=true;trustServerCertificate=true";
String user = "app_user";
String password = "StrongP@ssw0rd";
// 1. 載入驅動 (JDBC 4.0+ 可選,SPI 自動載入)
// Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
try (Connection conn = DriverManager.getConnection(url, user, password)) {
System.out.println("✅ 連線成功!");
System.out.println("資料庫版本: " + conn.getMetaData().getDatabaseProductVersion());
System.out.println("驅動版本: " + conn.getMetaData().getDriverVersion());
System.out.println("隔離級別: " + conn.getTransactionIsolation());
// 簡單查詢測試
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT @@VERSION AS version")) {
if (rs.next()) {
System.out.println("版本詳情: " + rs.getString("version"));
}
}
} catch (SQLException e) {
System.err.println("❌ 連線失敗: " + e.getMessage());
e.printStackTrace();
// 常見錯誤碼分析
analyzeError(e);
}
}
static void analyzeError(SQLException e) {
System.err.println("SQLState: " + e.getSQLState());
System.err.println("ErrorCode: " + e.getErrorCode());
switch (e.getErrorCode()) {
case 18456 -> System.err.println("🔑 登入失敗:帳號/密碼錯誤、帳號鎖定、或非 SQL 認證模式");
case 4060 -> System.err.println("🗄️ 資料庫不存在:databaseName 拼錯或未建立");
case 17182 -> System.err.println("🔌 連線超時:主機/埠口錯誤、防火牆阻擋、SQL Server 服務未啟動、TCP/IP 未啟用");
case 0, -1 -> System.err.println("🌐 網路不可達:主機名解析失敗、VPN/代理問題");
default -> System.err.println("📋 請查閱 Microsoft 官方錯誤碼文檔");
}
}
}
常見問題排查清單
| 錯誤現象 | 原因 | 解決方案 |
| No suitable driver found | 驅動 JAR 未在 classpath、版本不匹配 JDK | 檢查 Maven 依賴、確認 JAR 存在、JDBC 4.0+ 無需 Class.forName |
The TCP/IP connection to the host has failed | 主機/IP/埠錯誤、防火牆、SQL Server 未啟用 TCP/IP | telnet host 1433 測試、Configuration Manager 啟用 TCP/IP、防火牆放行 |
| Login failed for user | 密碼錯誤、帳號鎖定、非 SQL 認證模式 | SSMS 測試登入、重設密碼、啟用混合認證模式並重啟服務 |
| Certificate validation failed | 驅動預設驗證 SSL 憑證,自簽憑證失敗 | 開發加 trustServerCertificate=true;生產配置有效憑證或信任存儲 |
| Connection reset | 網路不穩、伺服器主動斷開、閒置超時 | HikariCP 設定 max-lifetime、connection-test-query、檢查網路 |
| Bulk insert 亂碼 | 字元編碼不匹配 | 連線字串加 sendStringParametersAsUnicode=true、資料庫欄位用 NVARCHAR |
效能優化建議
- 使用預編譯語句:
PreparedStatement 防注入、計畫快取重用
- 批次操作:
addBatch() + executeBatch(),配合 hibernate.jdbc.batch_size
- 適當索引:避免表掃描,使用
INCLUDE 欄覆蓋索引
- 分頁查詢:SQL Server 2012+
OFFSET ... FETCH,舊版用 ROW_NUMBER()
- 資料類型匹配:Java
String 對應 NVARCHAR,BigDecimal 對應 DECIMAL,避免隱式轉換