3.2.8.1.JdbcTemplate
作用:Spring JDBC 提供的一个模板类,简化了数据库操作,避免了样板代码。
JdbcTemplate 是 Spring 框架提供的一个用于简化 JDBC 编程的工具类,它通过模板方法模式(Template Method Pattern)封装了常见的数据库操作,帮助开发者以更简单的方式执行数据库操作,减少了很多冗余的代码。
3.2.8.1.1.JdbcTemplate 的作用
JdbcTemplate 提供了许多方法来执行 SQL 查询、更新操作以及批量操作等,并且自动处理资源管理(如连接、语句关闭等),避免了繁琐的异常处理和连接池管理,简化了 JDBC 的使用。
它通过使用 JDBC 内部的 Connection、Statement 和 ResultSet 对象,将数据库交互过程封装成简单的 API。
3.2.8.1.2.JdbcTemplate 的常见用法
1)创建 JdbcTemplate 实例
要使用 JdbcTemplate,需要注入一个数据源(DataSource)。Spring 会通过这个数据源来获取数据库连接。
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.datasource.DriverManagerDataSource; public class JdbcTemplateExample { public static void main(String[] args) { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/mydb"); dataSource.setUsername("root"); dataSource.setPassword("password"); JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource); // 使用 jdbcTemplate 执行查询和更新操作 } } |
如果是通过 Spring 配置文件或者 Java 配置进行集成,那么 JdbcTemplate 会自动注入数据源。
2)查询操作:query()
query() 方法用于执行一个查询操作,返回一个列表(通常是 List),该方法需要传入 SQL 查询语句和一个 RowMapper 实现,用于将 ResultSet 映射成 Java 对象。
import org.springframework.jdbc.core.RowMapper; import org.springframework.jdbc.core.JdbcTemplate; import java.util.List; public class JdbcTemplateExample { public static void main(String[] args) { JdbcTemplate jdbcTemplate = // 从容器中获取或手动创建 String sql = "SELECT * FROM users WHERE age > ?"; List<User> users = jdbcTemplate.query(sql, new Object[]{30}, new RowMapper<User>() { @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); user.setAge(rs.getInt("age")); return user; } }); for (User user : users) { System.out.println(user); } } } |
在上面的代码中:
query() 方法的第一个参数是 SQL 查询语句。
第二个参数是 SQL 参数(例如查询条件)。
第三个参数是 RowMapper,用于将每行 ResultSet 转换成 Java 对象。
3.2.8.1.3.查询操作:queryForObject()
queryForObject() 方法用于查询返回单一的结果,比如单行或单列的结果。
String sql = "SELECT COUNT(*) FROM users WHERE age > ?"; int count = jdbcTemplate.queryForObject(sql, new Object[]{30}, Integer.class); System.out.println("Users older than 30: " + count); |
在这个例子中,queryForObject() 返回一个整数值,它的第三个参数指定了返回结果的类型(Integer.class)。
3.2.8.1.4.更新操作:update()
update() 方法用于执行数据更新操作(如插入、更新或删除)。它返回受影响的行数。
String sql = "UPDATE users SET age = ? WHERE id = ?"; int rowsAffected = jdbcTemplate.update(sql, 35, 1); // 将 ID 为 1 的用户年龄更新为 35 System.out.println("Rows affected: " + rowsAffected); |
3.2.8.1.5.批量操作:batchUpdate()
batchUpdate() 用于批量更新,可以批量插入、更新或删除记录,提升性能。
String sql = "INSERT INTO users (name, age) VALUES (?, ?)"; List<Object[]> batchArgs = new ArrayList<>(); batchArgs.add(new Object[]{"John", 25}); batchArgs.add(new Object[]{"Jane", 30}); batchArgs.add(new Object[]{"Bob", 22}); int[] updateCounts = jdbcTemplate.batchUpdate(sql, batchArgs); System.out.println("Rows inserted: " + updateCounts.length); |
3.2.8.1.6.获取单个值:queryForObject() 和 queryForList()
除了返回一个对象或对象列表,JdbcTemplate 还可以用来查询数据库中的单个值或多个值。
例如,查询单个字段值可以使用 queryForObject() 方法:
String sql = "SELECT name FROM users WHERE id = ?"; String name = jdbcTemplate.queryForObject(sql, new Object[]{1}, String.class); System.out.println("User name: " + name); |
3.2.8.1.7.执行存储过程:callableStatement()
JdbcTemplate 还提供了执行存储过程的功能。例如,执行一个带有参数的存储过程:
String sql = "{call GetUserById(?, ?)}"; Map<String, Object> result = jdbcTemplate.call(connection -> { CallableStatement cs = connection.prepareCall(sql); cs.setInt(1, 1); // 设置存储过程参数 cs.registerOutParameter(2, Types.VARCHAR); // 注册输出参数 return cs; }, new ArrayList<>()); |
3.2.8.1.8.JdbcTemplate 的优点
1)简化 JDBC 编程:通过封装 Connection、PreparedStatement、ResultSet 的操作,减少了模板代码。
2)自动资源管理:自动管理数据库连接、Statement、ResultSet 的关闭,避免了开发者手动关闭资源。
3)异常转换:JdbcTemplate 会将 SQLException 转换为 Spring 的 DataAccessException,从而让异常处理更为统一。
4)SQL 参数绑定:支持用占位符传递参数,防止 SQL 注入。
3.2.8.1.9.JdbcTemplate 的常见异常
DataAccessException:JdbcTemplate 会把原本SQLException 封装为 DataAccessException。这个异常是 Spring 的数据访问异常体系的一部分,具有统一的异常处理机制。
常见的异常类有:
EmptyResultDataAccessException:查询结果为空时抛出。
IncorrectResultSizeDataAccessException:查询结果大小不符合预期时抛出。
3.2.8.1.10.与 JdbcTemplate 相关的组件
NamedParameterJdbcTemplate:这是 JdbcTemplate 的增强版,支持命名参数(例如 :name, :id),相对于位置参数更加易于维护和理解。
NamedParameterJdbcTemplate namedParameterJdbcTemplate=new NamedParameterJdbcTemplate(dataSource); String sql = "SELECT * FROM users WHERE id = :id"; Map<String, Object> params = new HashMap<>(); params.put("id", 1); User user = namedParameterJdbcTemplate.queryForObject(sql, params, new UserRowMapper()); |
SimpleJdbcTemplate:Spring 3.1 引入的更简化的 JdbcTemplate 版本,它的设计目标是简化数据库操作,提供更简洁的 API,但在 Spring 4.x 版本后被弃用。
