源自 Sun 官方論壇的 JDBC FAQ,涵蓋 JDBC 3.0 特性、驅動分類、連接建立、ResultSet 操作、異常診斷、性能調優、Applet 部署等全方位實戰問題。本文按主題重組,補充代碼示例與最佳實踐。
JDBC 3.0 是 JDBC 規範重大更新(JSR 54),核心新特性:
TYPE_SCROLL_INSENSITIVE、CONCUR_UPDATABLE)BOOLEAN、BLOB、CLOB、ARRAY、STRUCT、REF、DATALINKConnectionPoolDataSource、PooledConnection)僅提供有限子集,不支持可滾動 ResultSet、Savepoint 等高級特性。生產環境強烈建議使用純 Java 驅動(Type 3/4)。
| 類型 | 架構 | 代表 | 優/缺點 |
|---|---|---|---|
| Type 1 | JDBC-ODBC Bridge | Sun Bridge | 需 ODBC 驅動,平台相關,僅測試用 |
| Type 2 | Native API | Oracle OCI | 需客戶端庫,性能較好,部署複雜 |
| Type 3 | Net Protocol | IDA Server | 中間件轉發,純 Java,支持防火牆 |
| Type 4 | Thin Driver | MySQL Connector/J、Oracle Thin | 純 Java、直連數據庫、部署最簡、首選 |
查詢最新驅動列表:Sun JDBC Drivers Page
Class.forName("com.mysql.jdbc.Driver") 缺失或拼寫錯誤jdbc:mysql://localhost:3306/db vs jdbc:mysql//localhost/db)JDK 1.0.2(Netscape 3.0 等舊瀏覽器)不包含 JDBC API。解決方案:驅動廠商提供重命名包 jdbc.sql.*,Applet 中 import jdbc.sql.* 替代 java.sql.*,隨 Applet 下載。現代環境(JDK 1.1+)無此問題。
客戶機未配置系統 DSN(控制面板 → 管理工具 → 數據源 ODBC)。Bridge 僅作 ODBC 客戶端,**必須在客戶機配置 DSN**,不能指望讀取服務器端 DSN。
JDBC API 無整行獲取方法。getObject(int columnIndex) 仍按列訪問。性能瓶頸通常不在列獲取,而在網絡往返、獲取行數、大對象流式讀取。建議:
fetchSize 減少網絡交互getBinaryStream/getCharacterStream 流式讀取SELECT *,顯式列出所需列無直接 getRowCount()。三種方案:
rs.last(); int count = rs.getRow(); rs.beforeFirst();while(rs.next()) count++;SELECT COUNT(*) FROM ... 獨立查詢,利用數據庫優化器JDBC 規範每次 getString 返回新對象。緩解策略:
getBytes() + 字節數組池/緩存(需驅動支持)**不受信任 Applet 禁止使用**(安全限制:ODBC 是本地代碼,繞過沙箱)。受信任 Applet(簽名/企業內網)可用,但強烈建議改用 Type 4 純 Java 驅動,無需客戶端配置、可自動下載。
僅自帶 JDBC-ODBC Bridge。其他驅動需單獨下載安裝。JDK 6+ 引入 java.sql.Driver SPI 機制,驅動 JAR 放入 classpath 自動註冊,無需 Class.forName。
**不是**。同步方法序列化所有 ODBC 調用,多線程無併發優勢,且可能因數據庫鎖與 Bridge 信號量產生死鎖。
**不支持**。每連接僅允許一個打開的 Statement。
驅動僅實現 JDBC 1.0/2.0 核心,未實現可滾動 ResultSet。需升級 JDBC 3.0+ 驅動,且確認 DBMS 支持游標滾動,代碼創建 TYPE_SCROLL_INSENSITIVE 結果集。
// DriverManager 方式
DriverManager.setLogWriter(new PrintWriter(System.out));
// DataSource 方式
dataSource.setLogWriter(new PrintWriter(System.out));
// 連接池/分布式事務
poolDataSource.setLogWriter(...);
xaDataSource.setLogWriter(...);
輸出含連接建立、SQL 執行、參數綁定、結果集遍歷等完整鏈路,極利於排查 SQL 錯誤、參數類型不匹配、事務邊界問題。