Spring JDBC 抽象框架由四個核心包組成,層層遞進:
org.springframework.jdbc.core:核心功能,含 JdbcTemplate、SQLExceptionTranslator、DAO 基類org.springframework.jdbc.datasource:數據源工具類與簡易實現,支援非容器測試org.springframework.jdbc.object:將查詢、更新、存儲過程封裝為可重用線程安全對象(RDBMS 操作對象)org.springframework.jdbc.support:SQLException 轉換與工具類所有 JDBC 異常均轉換為 org.springframework.dao 中的未檢查異常,無需強制捕獲,便於按需恢復或向上拋出。
JdbcTemplate 是最重要的類,負責資源獲取/釋放、Statement 創建/執行、結果集迭代、參數綁定、異常轉換。使用者僅需提供 SQL 與回調接口實現:
PreparedStatementCreator:創建 PreparedStatementCallableStatementCreator:創建 CallableStatementRowCallbackHandler:逐行提取結果可直接實例化或作為 Bean 注入,所有 SQL 執行自動記錄日誌。
| 實現類 | 適用場景 | 特點 |
|---|---|---|
| DriverManagerDataSource | 測試/獨立環境 | 每次獲取新連接,非池化 |
| SingleConnectionDataSource | 單線程測試 | 單連接複用,suppressClose 防止過早關閉 |
| DataSourceUtils | 輔助工具 | JNDI 獲取、線程綁定連接、事務管理配合 |
| SmartDataSource | 接口擴展 | 可判斷操作後是否關閉連接 |
| AbstractDataSource | 自定義數據源基類 | 處理通用邏輯 |
DataSourceTransactionManager:單數據源事務管理器,綁定連接到線程,支援隔離級與查詢超時,可替代 JTA 用於單資源場景。
JdbcTemplate jt = new JdbcTemplate(dataSource);
jt.execute("create table mytable (id integer, name varchar(100))");
int count = jt.queryForInt("select count(*) from mytable");
String name = (String) jt.queryForObject("select name from mytable", String.class);
List
jt.update("update mytable set name = ? where id = ?", new Object[] {name, new Integer(id)});
默認使用 SQLErrorCodeSQLExceptionTranslator,基於 sql-error-codes.xml 與數據庫元數據匹配 ErrorCode,精度優於 SQLState。可繼承自定義:
public class MyTranslator extends SQLErrorCodeSQLExceptionTranslator {
protected DataAccessException customTranslate(String task, String sql, SQLException sqlex) {
if (sqlex.getErrorCode() == -12345)
return new DeadlockLoserDataAccessException(task, sqlex);
return null; // 其餘交給默認處理
}
}
// 使用
jt.setExceptionTranslator(new MyTranslator());
private class CustomerMappingQuery extends MappingSqlQuery {
public CustomerMappingQuery(DataSource ds) {
super(ds, "SELECT id, name FROM customer WHERE id = ?");
super.declareParameter(new SqlParameter("id", Types.INTEGER));
compile();
}
public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
Customer c = new Customer();
c.setId((Integer) rs.getObject("id"));
c.setName(rs.getString("name"));
return c;
}
}
// 執行
List list = new CustomerMappingQuery(ds).execute(new Object[]{id});
public class UpdateCreditRating extends SqlUpdate {
public UpdateCreditRating(DataSource ds) {
setDataSource(ds);
setSql("update customer set credit_rating = ? where id = ?");
declareParameter(new SqlParameter(Types.NUMERIC));
declareParameter(new SqlParameter(Types.NUMERIC));
compile();
}
public int run(int id, int rating) {
return update(new Object[]{new Integer(rating), new Integer(id)});
}
}
public class MyStoredProcedure extends StoredProcedure {
public static final String SQL = "sysdate";
public MyStoredProcedure(DataSource ds) {
setDataSource(ds);
setFunction(true);
setSql(SQL);
declareParameter(new SqlOutParameter("date", Types.DATE));
compile();
}
public Map execute() { return execute(new HashMap()); }
}
public int countRows() {
SqlFunction sf = new SqlFunction(dataSource, "select count(*) from mytable");
sf.compile();
return sf.run();
}