本例演示封裝 PreparedStatement 通用執行器:自動綁定參數、區分查詢與 DML、結果集映射為 Vector、資源自動管理。
public class StatementConn {
private static String url, username, password;
Connection con = null;
PreparedStatement updStmt = null;
public Connection conn() { ... } // 獲取連接
public void close() { try { con.close(); } catch (Throwable e) {} con = null; }
// 參數綁定核心
private PreparedStatement getStatement(String sql, Vector vCondition) throws SQLException {
int i = 0; Object temp;
updStmt = conn().prepareStatement(sql);
for (i = 0; i < vCondition.size(); i++) {
temp = vCondition.elementAt(i);
if (temp instanceof Integer) updStmt.setInt(i+1, ((Integer)temp).intValue());
else if (temp instanceof Double) updStmt.setDouble(i+1, ((Double)temp).doubleValue());
else if (temp instanceof String) updStmt.setString(i+1, temp.toString().trim());
else updStmt.setObject(i+1, temp);
}
return updStmt;
}
private void closeUpdStmt() { try { if (updStmt != null) updStmt.close(); } catch (Throwable e) {} updStmt = null; }
// 統一執行入口
public Object execute(String sql, Vector vCondition) throws SQLException, Exception {
ResultSet rs = null; Vector vResult = null;
try {
if (!isSelect(sql)) { // DML
Integer iResult = new Integer(getStatement(sql, vCondition).executeUpdate());
return iResult;
} else { // SELECT
rs = getStatement(sql, vCondition).executeQuery();
int columnCount = rs.getMetaData().getColumnCount();
vResult = new Vector();
while (rs.next()) {
Vector vTemp = new Vector();
for (int i = 0; i < columnCount; i++) {
String sTemp = rs.getString(i+1);
vTemp.addElement(sTemp == null ? "" : sTemp.trim());
}
vResult.addElement(vTemp);
}
rs.close(); closeUpdStmt();
}
} catch (Exception e1) { throw e1; }
finally { close(); }
return vResult;
}
protected boolean isSelect(String psql) {
String sql = psql.trim().toUpperCase();
return sql.indexOf("SELECT") == 0;
}
public static void main(String[] arg) { ... }
public static void demo() {
StatementConn oc = new StatementConn();
String sql = "select * from TBL_USER where id > ?";
Vector vCondition = new Vector();
vCondition.addElement(new Integer(3));
Vector vResult = (Vector) oc.execute(sql, vCondition);
for (int i = 0; i < vResult.size(); i++) System.out.println(vResult.elementAt(i));
}
}
| 優勢 | 說明 |
|---|---|
| 防 SQL 注入 | 參數化綁定,數據與代碼分離,徹底消除拼接注入風險 |
| 性能優化 | 預編譯緩存执行計劃,重複執行無需再次解析優化 |
| 類型安全 | setXxx() 強類型綁定,避免隱式轉換錯誤 |
| 可讀性 | SQL 模板與參數分離,複雜查詢更清晰 |
| 批量處理 | addBatch()/executeBatch() 大幅提升批量寫入吞吐 |
| Java 類型 | setXxx 方法 | JDBC 類型 |
|---|---|---|
| String | setString | VARCHAR/CHAR |
| int/Integer | setInt | INTEGER |
| long/Long | setLong | BIGINT |
| double/Double | setDouble | DOUBLE |
| float/Float | setFloat | REAL |
| boolean/Boolean | setBoolean | BIT/BOOLEAN |
| byte[] | setBytes | BLOB/VARBINARY |
| Date/Time/Timestamp | setDate/setTime/setTimestamp | DATE/TIME/TIMESTAMP |
| BigDecimal | setBigDecimal | DECIMAL/NUMERIC |
| InputStream/Reader | setBinaryStream/setCharacterStream | BLOB/CLOB |
| 任意對象 | setObject | 驅動自動映射 |
List<Map<String,Object>> 替代 Vector@Repository
public class UserDao {
@Autowired JdbcTemplate jdbcTemplate;
public List findByIdGreaterThan(int id) {
return jdbcTemplate.query(
"SELECT * FROM TBL_USER WHERE id > ?",
new Object[]{id},
(rs, rowNum) -> new User(rs.getInt("id"), rs.getString("name"), ...)
);
}
}
Spring JdbcTemplate 封裝了連接管理、參數綁定、結果映射、異常轉換,生產環境強烈推薦。