JdbcTemplate简化数据访问

wen java案例 3

JdbcTemplate 简化数据访问

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

JdbcTemplate简化数据访问

传统 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 框架复杂特性的项目。

抱歉,评论功能暂时关闭!