// 典型樣板代碼
Connection con = null; PreparedStatement ps = null; ResultSet rs = null;
try {
con = getConnection();
ps = con.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) { list.add(rs.getString(1)); }
} catch (SQLException e) { e.printStackTrace(); }
finally {
try { rs.close(); ps.close(); con.close(); } catch (SQLException e) { e.printStackTrace(); }
}
四大罪狀:資源管理樣板碼泛濫、`SQLException` 失去語義、錯誤碼跨資料庫不一致、業務邏輯被基礎設施代碼淹沒。
| 特性 | 傳統 JDBC | Spring JDBC |
|---|---|---|
| 資源管理 | 手動 try-finally | 模板模式自動釋放 |
| 異常體系 | 單一 SQLException | 分層 `DataAccessException` 體系 |
| 資料映射 | 手動 `rs.getXxx()` | `RowMapper` / `ResultSetExtractor` |
| DataSource 獲取 | 硬編碼/單例 | IoC 容器注入 |
| 測試性 | 難以 Mock | 易於單元測試 (嵌入式 DB) |
org.springframework.jdbc
├── core
│ ├── JdbcTemplate # 核心模板類
│ ├── RowMapper # 行映射策略介面
│ ├── RowCallbackHandler # 流式處理回調
│ └── simple # SimpleJdbcInsert/Call 簡化 API
├── datasource
│ ├── DriverManagerDataSource # 簡單實現 (測試用)
│ └── ... # C3P0/DBCP/Hikari 整合
├── object # RDBMS Operation 物件化 (可重用、線程安全)
└── support # SQLErrorCodeSQLExceptionTranslator 等工具
public interface TaskDao {
List getTaskNames();
}
public class TaskJdbcDao extends JdbcDaoSupport implements TaskDao {
@Override
public List getTaskNames() {
return getJdbcTemplate().query(
"SELECT task_name FROM tasks",
new RowMapper() {
@Override
public String mapRow(ResultSet rs, int rowNum) throws SQLException {
return rs.getString(1);
}
}
);
}
}
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
<property name="username" value="scott"/>
<property name="password" value="tiger"/>
</bean>
<bean id="taskDao" class="com.example.TaskJdbcDao">
<property name="dataSource" ref="dataSource"/>
</bean>
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
TaskDao dao = ctx.getBean("taskDao", TaskDao.class);
dao.getTaskNames().forEach(System.out::println);
// Service 介面
public interface TaskService {
List getTaskNames();
}
// Service 實現 - 依賴 DAO 介面
@Service
public class TaskServiceImpl implements TaskService {
private TaskDao taskDao;
@Autowired
public void setTaskDao(TaskDao taskDao) { this.taskDao = taskDao; }
@Override
public List getTaskNames() { return taskDao.getTaskNames(); }
}
// XML 裝配
<bean id="taskService" class="com.example.TaskServiceImpl">
<property name="taskDao" ref="taskDao"/>
</bean>
Spring JDBC 以 模板模式消除樣板碼、異常體系賦予語義、IoC 實現鬆耦合,讓開發者聚焦 SQL 與業務映射。雖 ORM (Hibernate/JPA) 更主流,但對於複雜報表、批量處理、存儲過程調用、Legacy 系統改造,Spring JDBC 仍是輕量、可控、高效的首選利器。