JdbcTemplate 简化数据访问
JdbcTemplate 是 Spring 框架提供的一个核心 JDBC 抽象层,它极大地简化了使用 JDBC 进行数据库操作的开发工作。

传统 JDBC 的问题
使用原生 JDBC 时,你需要处理大量样板代码:
// 传统 JDBC 示例 - 查询用户
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
User user = null;
try {
conn = dataSource.getConnection();
ps = conn.prepareStatement("SELECT * FROM users WHERE id = ?");
ps.setLong(1, userId);
rs = ps.executeQuery();
if (rs.next()) {
user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
}
} catch (SQLException e) {
// 处理异常
throw new RuntimeException(e);
} finally {
// 手动关闭资源
if (rs != null) try { rs.close(); } catch (SQLException e) { }
if (ps != null) try { ps.close(); } catch (SQLException e) { }
if (conn != null) try { conn.close(); } catch (SQLException e) { }
}
JdbcTemplate 的简化版本
// 使用 JdbcTemplate
User user = jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = ?",
new BeanPropertyRowMapper<>(User.class),
userId
);
JdbcTemplate 核心优势
自动资源管理
- 自动获取和释放数据库连接
- 自动关闭 Statement 和 ResultSet
- 避免资源泄漏
异常处理
- 将 SQLException 转换为 Spring 的 DataAccessException
- 提供更具体的异常类型(如 DuplicateKeyException)
- 支持声明式事务管理
简化 CRUD 操作
查询操作:
// 查询单个对象
User user = jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = ?",
new BeanPropertyRowMapper<>(User.class),
1L
);
// 查询列表
List<User> users = jdbcTemplate.query(
"SELECT * FROM users WHERE age > ?",
new BeanPropertyRowMapper<>(User.class),
18
);
// 查询单值
Integer count = jdbcTemplate.queryForObject(
"SELECT COUNT(*) FROM users",
Integer.class
);
更新操作:
// 插入
jdbcTemplate.update(
"INSERT INTO users (name, email) VALUES (?, ?)",
"张三", "zhang@example.com"
);
// 更新
jdbcTemplate.update(
"UPDATE users SET email = ? WHERE id = ?",
"new@example.com", 1L
);
// 删除
jdbcTemplate.update(
"DELETE FROM users WHERE id = ?",
1L
);
批量操作支持
// 批量插入
List<Object[]> batchArgs = new ArrayList<>();
batchArgs.add(new Object[] {"张三", "zhang@example.com"});
batchArgs.add(new Object[] {"李四", "li@example.com"});
jdbcTemplate.batchUpdate(
"INSERT INTO users (name, email) VALUES (?, ?)",
batchArgs
);
命名参数支持
// 使用 NamedParameterJdbcTemplate
NamedParameterJdbcTemplate namedJdbc =
new NamedParameterJdbcTemplate(jdbcTemplate);
Map<String, Object> params = new HashMap<>();
params.put("minAge", 18);
params.put("maxAge", 60);
List<User> users = namedJdbc.query(
"SELECT * FROM users WHERE age BETWEEN :minAge AND :maxAge",
params,
new BeanPropertyRowMapper<>(User.class)
);
使用 RowMapper 自定义映射
// 自定义 RowMapper
public class UserRowMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
user.setCreatedAt(rs.getTimestamp("created_at"));
return user;
}
}
// 使用自定义 RowMapper
List<User> users = jdbcTemplate.query(
"SELECT * FROM users WHERE age > ?",
new UserRowMapper(),
18
);
配置示例
@Configuration
public class JdbcConfig {
@Bean
public DataSource dataSource() {
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("root");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public JdbcTemplate jdbcTemplate(DataSource dataSource) {
return new JdbcTemplate(dataSource);
}
}
完整示例:用户服务
@Repository
public class UserRepository {
@Autowired
private JdbcTemplate jdbcTemplate;
public User findById(Long id) {
return jdbcTemplate.queryForObject(
"SELECT * FROM users WHERE id = ?",
new BeanPropertyRowMapper<>(User.class),
id
);
}
public List<User> findByAgeRange(int min, int max) {
return jdbcTemplate.query(
"SELECT * FROM users WHERE age BETWEEN ? AND ?",
new UserRowMapper(),
min, max
);
}
public int save(User user) {
return jdbcTemplate.update(
"INSERT INTO users (name, email, age) VALUES (?, ?, ?)",
user.getName(), user.getEmail(), user.getAge()
);
}
}
JdbcTemplate 通过提供模板方法模式,封装了 JDBC 的重复性工作,让开发者只需关注 SQL 和数据处理逻辑,它解决了传统 JDBC 编程中的:
- ✅ 资源管理:自动处理连接、语句、结果集
- ✅ 异常处理:统一的异常层次结构
- ✅ 代码简化:减少大量样板代码
- ✅ 灵活性:支持自定义 RowMapper 和回调接口
- ✅ 集成性:与 Spring 事务管理无缝集成
这使得 JdbcTemplate 成为 Spring 应用中数据访问层的优秀选择,特别适合那些不需要 ORM 框架复杂特性的项目。