雖然 SQL Server 2000 已於 2013 年停止主流支持,但金融、製造、政府等領域仍有大量核心系統運行在舊版本上。JTDS(jTDS)作為開源、純 Java、Type 4 驅動,曾長期是連接舊版 SQL Server 的首選。本文記錄真實遷移維護中的連接參數、版本兼容、效能調優、編碼陷阱,並給出現代替代方案。
net.sourceforge.jtds
jtds
1.3.1
# 基礎格式
jdbc:jtds:sqlserver://:;DatabaseName=
# 生產常用完整參數
jdbc:jtds:sqlserver://192.168.0.15:1433;DatabaseName=test;charset=utf-8;ssl=request;instance=SQLEXPRESS;prepareSQL=3;sendStringParametersAsUnicode=false
| 參數 | 說明 | 推薦值/備註 |
|---|---|---|
| host | 服務器 IP 或主機名 | |
| port | 默認 1433,命名實例需 SQL Browser 服務 | 動態端口時需指定 instance |
| DatabaseName | 目標數據庫 | 必填 |
| charset | 字符集編碼 | utf-8(防止中文亂碼) |
| ssl | SSL 模式 | off/request/require/verify-ca/verify-full |
| instance | 命名實例名 | 如 SQLEXPRESS,替代端口號 |
| prepareSQL | PreparedStatement 緩存級別 | 0=不緩存, 3=緩存所有(默認),大批量插入建議 0 |
| sendStringParametersAsUnicode | 字符串參數是否發送為 Unicode | false(避免隱式轉換導致索引失效,極其重要!) |
| useCursors | 是否使用服務端游標 | true(大結果集流式讀取) |
| maxStatements | 語句緩存大小 | 配合 prepareSQL 使用 |
| loginTimeout | 登錄超時(秒) | 10-30 |
| socketTimeout | 網絡讀寫超時(秒) | 30-60,防止死連接 |
import java.sql.*;
public class JtdsConnectionTest {
public static void main(String[] args) {
String url = "jdbc:jtds:sqlserver://192.168.0.15:1433;DatabaseName=test;charset=utf-8;sendStringParametersAsUnicode=false";
String user = "sa";
String password = "123";
Connection conn = null;
try {
// 1. 加載驅動(JDBC 4.0+ 可省略,保留兼容)
Class.forName("net.sourceforge.jtds.jdbc.Driver");
System.out.println("驅動加載成功");
// 2. 獲取連接計時
long start = System.currentTimeMillis();
conn = DriverManager.getConnection(url, user, password);
long elapsed = System.currentTimeMillis() - start;
System.out.printf("連接成功!耗時: %d ms%n", elapsed);
// 3. 簡單驗證查詢
try (Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT @@VERSION")) {
if (rs.next()) {
System.out.println("SQL Server 版本: " + rs.getString(1));
}
}
// 4. 獲取數據庫元數據
DatabaseMetaData meta = conn.getMetaData();
System.out.printf("驅動版本: %s %s%n", meta.getDriverName(), meta.getDriverVersion());
System.out.printf("JDBC 版本: %d.%d%n", meta.getJDBCMajorVersion(), meta.getJDBCMinorVersion());
} catch (ClassNotFoundException e) {
System.err.println("驅動類未找到,請檢查依賴: " + e.getMessage());
} catch (SQLException e) {
printSQLException(e);
} finally {
closeQuietly(conn);
}
}
private static void printSQLException(SQLException e) {
while (e != null) {
System.err.printf("SQLState: %s, ErrorCode: %d, Message: %s%n",
e.getSQLState(), e.getErrorCode(), e.getMessage());
e = e.getNextException();
}
}
private static void closeQuietly(AutoCloseable... resources) {
for (AutoCloseable r : resources) {
if (r != null) {
try { r.close(); } catch (Exception ignore) {}
}
}
}
}
現象:插入中文變亂碼,或 WHERE 條件中文無法匹配。
原因:JTDS 默認將 String 參數作為 NVARCHAR (Unicode) 發送,導致:
解決:URL 添加 sendStringParametersAsUnicode=false,強制發送 VARCHAR 參數。
現象:SELECT * FROM big_table 導致 Heap Memory 爆炸。
原因:默認客戶端游標一次性將所有行拉取到 JVM 內存。
解決:
url += ";useCursors=true"; // 服務端游標
stmt.setFetchSize(1000); // 每次抓取行數
// 或使用 try-with-resources 確保 ResultSet 及時關閉釋放服務端資源
現象:DDL 修改表結構後,舊 PreparedStatement 拋出異常或數據錯誤。
解決:DDL 操作後重啟應用,或關鍵路徑設置 prepareSQL=0 禁用緩存。
現象:InaccessibleObjectException。
解決:啟動參數添加 --add-opens java.base/java.lang=ALL-UNNAMED,或遷移至 mssql-jdbc。
微軟官方驅動 com.microsoft.sqlserver:mssql-jdbc 現已開源、積極維護、支援 JDK 8-21、JDBC 4.2/4.3、Always Encrypted、Azure AD 認證、Kerberos、高可用。
com.microsoft.sqlserver
mssql-jdbc
12.4.2.jre11
# JTDS
jdbc:jtds:sqlserver://host:1433;DatabaseName=db;charset=utf-8
# mssql-jdbc
jdbc:sqlserver://host:1433;databaseName=db;encrypt=true;trustServerCertificate=true;characterEncoding=UTF-8
net.sourceforge.jtds.jdbc.Driver → com.microsoft.sqlserver.jdbc.SQLServerDriver(JDBC 4.0+ 自動加載,可省略)
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:jtds:sqlserver://192.168.0.15:1433;DatabaseName=test;charset=utf-8;sendStringParametersAsUnicode=false");
config.setUsername("sa");
config.setPassword("123");
config.setDriverClassName("net.sourceforge.jtds.jdbc.Driver"); // 可省略
config.setMaximumPoolSize(20);
config.setConnectionTimeout(10000);
config.setIdleTimeout(300000);
config.setMaxLifetime(1800000);
config.setPoolName("SQLServerPool");
// 關鍵:連接驗證查詢
config.setConnectionTestQuery("SELECT 1");
config.setValidationTimeout(5000);
DataSource ds = new HikariDataSource(config);
JTDS 連接 SQL Server 2000/2005/2008 的核心要點:
charset=utf-8、sendStringParametersAsUnicode=falseuseCursors=true + setFetchSizeprepareSQL--add-opens 或遷移官方驅動本文測試代碼採用 try-with-resources、靜態工具方法、異常鏈打印,可直接作為健康檢查、啟動驗證、監控探針使用。