JdbcTemplate 核心方法分類
| 類別 | 方法 | 用途 |
| 執行更新 | update(sql, ...) | INSERT/UPDATE/DELETE,回傳影響行數 |
batchUpdate(sqlList) | 批次處理,效能大幅提升 |
| 查詢 | query(sql, RowMapper) | 多行映射為對象列表 |
queryForObject(sql, ...) | 單行單值/對象,無結果拋 EmptyResultDataAccessException |
queryForList(sql, ...) | 直接回傳 List<Map>,無需自定義映射 |
| DDL/通用 | execute(sql) | CREATE/DROP/任意 SQL,回傳 void |
| 存儲過程/函數 | call(CallableStatementCreator, params) | IN/OUT/INOUT 參數、ResultSet 回傳 |
回調體系:JdbcTemplate 的擴展點
1. 語句創建回調
PreparedStatementCreator:createPreparedStatement(Connection) → 自建 PreparedStatement
CallableStatementCreator:同理建立 CallableStatement
2. 參數綁定回調
PreparedStatementSetter:setValues(PreparedStatement) → 手動綁定參數
BatchPreparedStatementSetter:批次版,需實作 setValues(ps, i) + getBatchSize()
3. 通用操作回調(最靈活)
ConnectionCallback:拿到 Connection 隨意操作
StatementCallback / PreparedStatementCallback / CallableStatementCallback
4. 結果集處理回調
| 介面 | 方法 | 特點 |
RowMapper<T> | mapRow(ResultSet, rowNum) | 逐行映射,JdbcTemplate 自動迭代 next() |
RowCallbackHandler | processRow(ResultSet) | 逐行處理,無返回值,適合流式處理/寫入檔案 |
ResultSetExtractor<T> | extractData(ResultSet) | 一次性拿到整個 ResultSet,自行控制迭代,適合複雜聚合 |
實戰代碼範例
基本查詢 + RowMapper
List<User> users = jdbcTemplate.query(
"SELECT id, name, email FROM users WHERE status = ?",
new Object[]{1},
(rs, rowNum) -> new User(rs.getLong("id"), rs.getString("name"), rs.getString("email"))
);
單值查詢
Integer count = jdbcTemplate.queryForObject(
"SELECT COUNT(*) FROM users WHERE status = ?", Integer.class, 1);
批次插入
jdbcTemplate.batchUpdate(
"INSERT INTO users(name, email) VALUES(?, ?)",
new BatchPreparedStatementSetter() {
public void setValues(PreparedStatement ps, int i) throws SQLException {
User u = users.get(i);
ps.setString(1, u.getName());
ps.setString(2, u.getEmail());
}
public int getBatchSize() { return users.size(); }
});
存儲過程調用 (MySQL)
Map<String, Object> out = jdbcTemplate.call(
new CallableStatementCreator() {
public CallableStatement createCallableStatement(Connection con) throws SQLException {
CallableStatement cs = con.prepareCall("{call proc_user_stats(?, ?)}");
cs.setInt(1, userId);
cs.registerOutParameter(2, Types.INTEGER);
return cs;
}
},
Arrays.asList(
new SqlParameter("p_user_id", Types.INTEGER),
new SqlOutParameter("p_total", Types.INTEGER)
));
Integer total = (Integer) out.get("p_total");
最佳實踐建議
- 優先使用便利方法 (
queryForObject, update) 簡化代碼
- 複雜映射/邏輯 才用
RowMapper/ResultSetExtractor
- 批次操作 必用
batchUpdate,單條循環極慢
- DataSource 配置連接池 (HikariCP/Druid),JdbcTemplate 本身不管理連接
- 命名參數 可用
NamedParameterJdbcTemplate 提升可讀性
- 事務管理 配合
@Transactional 或 TransactionTemplate,JdbcTemplate 無事務感知
總結
JdbcTemplate 以模板方法模式封裝 JDBC 固定流程,暴露回調介面讓開發者專注 SQL 與映射邏輯。掌握五大方法類別與四類回調,即可應對 95% 持久層場景,代碼簡潔且效能可控。