首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 程式設計入門

JTDS 1.3.1 連接 SQL Server 2000/2005/2008 完整指南與避坑實錄

     編輯:Java 程式設計入門

前言:為什麼 2024 年還在用 JTDS 連 SQL Server 2000?

雖然 SQL Server 2000 已於 2013 年停止主流支持,但金融、製造、政府等領域仍有大量核心系統運行在舊版本上。JTDS(jTDS)作為開源、純 Java、Type 4 驅動,曾長期是連接舊版 SQL Server 的首選。本文記錄真實遷移維護中的連接參數、版本兼容、效能調優、編碼陷阱,並給出現代替代方案。

1. 核心依賴與版本選擇




    net.sourceforge.jtds
    jtds
    1.3.1




2. 連接 URL 完整參數解析


# 基礎格式
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(防止中文亂碼)
sslSSL 模式off/request/require/verify-ca/verify-full
instance命名實例名如 SQLEXPRESS,替代端口號
prepareSQLPreparedStatement 緩存級別0=不緩存, 3=緩存所有(默認),大批量插入建議 0
sendStringParametersAsUnicode字符串參數是否發送為 Unicodefalse(避免隱式轉換導致索引失效,極其重要!)
useCursors是否使用服務端游標true(大結果集流式讀取)
maxStatements語句緩存大小配合 prepareSQL 使用
loginTimeout登錄超時(秒)10-30
socketTimeout網絡讀寫超時(秒)30-60,防止死連接

3. 完整連接測試代碼(含效能計時、資源安全釋放)


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) {}
            }
        }
    }
}

4. 核心避坑實錄

坑 1:中文亂碼 —— sendStringParametersAsUnicode=false

現象:插入中文變亂碼,或 WHERE 條件中文無法匹配。

原因:JTDS 默認將 String 參數作為 NVARCHAR (Unicode) 發送,導致:

  • 表列為 VARCHAR 時發生隱式轉換,索引失效
  • 排序規則衝突導致比較異常

解決:URL 添加 sendStringParametersAsUnicode=false,強制發送 VARCHAR 參數。

坑 2:大數據量查詢 OOM —— useCursors=true

現象:SELECT * FROM big_table 導致 Heap Memory 爆炸。

原因:默認客戶端游標一次性將所有行拉取到 JVM 內存。

解決:


url += ";useCursors=true"; // 服務端游標
stmt.setFetchSize(1000);   // 每次抓取行數
// 或使用 try-with-resources 確保 ResultSet 及時關閉釋放服務端資源

坑 3:PreparedStatement 緩存導致元數據變更失效

現象:DDL 修改表結構後,舊 PreparedStatement 拋出異常或數據錯誤。

解決:DDL 操作後重啟應用,或關鍵路徑設置 prepareSQL=0 禁用緩存。

坑 4:JDK 11+ 模塊化導致反射訪問內部類失敗

現象:InaccessibleObjectException。

解決:啟動參數添加 --add-opens java.base/java.lang=ALL-UNNAMED,或遷移至 mssql-jdbc。

5. 遷移建議:JTDS → Microsoft JDBC Driver (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 

URL 遷移對照


# 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+ 自動加載,可省略)
  • DataSource 配置:僅修改 URL 與驅動類名
  • SQL 語法:T-SQL 通用,無需變動

6. 連接池整合(HikariCP + JTDS/mssql-jdbc)


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 的核心要點:

  1. URL 必帶 charset=utf-8、sendStringParametersAsUnicode=false
  2. 大結果集必開 useCursors=true + setFetchSize
  3. DDL 變更需重啟或禁用 prepareSQL
  4. JDK 11+ 需添加 --add-opens 或遷移官方驅動
  5. 生產環境強烈建議遷移至 mssql-jdbc,獲得長期支持與新特性

本文測試代碼採用 try-with-resources、靜態工具方法、異常鏈打印,可直接作為健康檢查、啟動驗證、監控探針使用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved