此範例示範將 SQL Server 資料庫連線、查詢、更新操作封裝為 JavaBean,採用 JDBC-ODBC Bridge 驅動 (已淘汰,僅供教學參考),部署於 Web 應用 WEB-INF/classes 供 JSP/Servlet 直接使用。
public class conndb implements Serializable {
private Connection conn;
private ResultSet rs;
private int count;
private String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
private String url = "jdbc:odbc:MySQL"; // ODBC 系統 DSN 名稱
private String user = "dxaw";
private String password = "123";
public conndb() {
try { Class.forName(driver); } catch (Exception e) {}
}
// 查詢回傳可捲動、可更新的 ResultSet
public ResultSet executeQuery(String sql) {
try {
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = stmt.executeQuery(sql);
} catch (Exception e) {}
return rs;
}
// 更新操作 (INSERT/UPDATE/DELETE)
public void executeUpdate(String sql) {
try {
conn = DriverManager.getConnection(url, user, password);
Statement stmt = conn.createStatement();
stmt.executeUpdate(sql); // 原碼誤用 executeQuery,此處修正
} catch (Exception e) {}
}
}
<%@ page import="conn.db.conndb" %>
<%
conndb db = new conndb();
ResultSet rs = db.executeQuery("SELECT * FROM products");
while (rs.next()) {
out.println(rs.getString("name") + "<br>");
}
rs.close();
%>
| 問題 | 說明 | 現代解決方案 |
|---|---|---|
| JDBC-ODBC Bridge | Java 8 移除,效能差、平台相依 | 使用廠商原生 JDBC 驅動 (Microsoft JDBC Driver for SQL Server) |
| 硬編碼連線參數 | 帳密寫死程式碼,部署困難、安全風險 | 外部化設定 (properties、YAML、環境變數、JNDI DataSource) |
| 每次操作新建連線 | 效能極差,無法支援併發 | 連線池 (HikariCP、DBCP2、Tomcat JDBC Pool) |
| ResultSet/Connection 當作欄位 | 非執行緒安全,併發下資料錯亂 | 區域變數 + try-with-resources 確保關閉 |
| 吞沒例外 | catch 空實作,錯誤無法追蹤 | 拋出自訂例外、統一錯誤處理、記錄日誌 |
| Statement 非參數化 | SQL 注入高風險 | PreparedStatement + 參數綁定 |
public class SqlServerDao {
private DataSource dataSource; // 注入 HikariDataSource
public List findAll() {
String sql = "SELECT id, name, price FROM products";
try (Connection conn = dataSource.getConnection();
PreparedStatement ps = conn.prepareStatement(sql);
ResultSet rs = ps.executeQuery()) {
List list = new ArrayList<>();
while (rs.next()) {
list.add(new Product(rs.getInt("id"), rs.getString("name"), rs.getBigDecimal("price")));
}
return list;
} catch (SQLException e) { throw new DaoException("Query failed", e); }
}
}