@[TOC](Spring JDBC(JDBCTemplate))
数据库连接池的弊端
前情提要: JDBC数据库连接池.
在上一篇中数据库连接池虽然已经对JDBC的连接和释放做了优化,避免了资源的浪费,但在数据的操作上并未做出任何的改善,特别是在查询封装数据时更为麻烦。
举个例子,获取封装一个学生信息表,则需要将数据每一行中的每一列取出来再封装到学生类中打包到列表中,需要一大串的代码,麻烦且复杂
public static void main(String[] args) {
Connection connection = DruidUtils.getConnection();
try {
Statement statement = connection.createStatement();
ResultSet resultSet = statement.executeQuery("select * from b");
List<Student> list = new ArrayList<>();
while (resultSet.next()) {
int id = resultSet.getInt("id");
String name = resultSet.getString("name");
int age = resultSet.getInt("age");
String sex = resultSet.getString("sex");
String local = resultSet.getString("local");
String phone = resultSet.getString("phone");
Student student = new Student();
student.setId(id);
student.setName(name);
student.setAge(age);
student.setLocal(local);
student.setPhone(phone);
student.setSex(sex);
list.add(student);
}
} catch (SQLException e) {
e.printStackTrace();
}finally {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
概述
本文所有资源都可到百度云下载
链接:https://pan.baidu.com/s/1EkEXRoMTiRN1GvXrGAx62g
提取码:j872
由spring框架对JDBC的简单封装,提供一个JDBCTemplate对象简化JDBC的数据操作。
使用步骤
导入jar包
获取JDBCTemplate对象
需要依赖于连接池的数据源DataSource
JdbcTemplate jdbcTemplate = new JdbcTemplate(DruidUtils.getDataSource());
操作数据
先创建一个数据表
JDBCTemplate采用了PreparedStatement预先编译,提高 SQL 的执行效率和避免sql注入攻击,sql语句的数据采用?占位符代替
增删改返回的结果都为影响数据表的行数
- 增加数据
jdbcTemplate.update("INSERT INTO b VALUES(?,?,?,?,?,?)", null, "a", 10, "男", "北京", "111");
- 删除数据
jdbcTemplate.update("DELETE FROM b WHERE id=?", 1);
- 修改数据
jdbcTemplate.update("UPDATE b SET age=? WHERE id=?", 20, 2);
- 查询数据
- queryForMap
将查询的数据结果封装到Map<String, Object>集合中,列名为集合的key,数据值为集合的value
需要注意的是,此查询结果有且仅有一条,查询的结果大于或小于一条是都会报错。
例如查询整个数据表
jdbcTemplate.queryForMap("select * from b");
则会发生IncorrectResultSizeDataAccessException异常,因为queryForMap期望获取的结果大小为1,可是返回的结果且为4
正确示范:
Map<String, Object> map = jdbcTemplate.queryForMap("select * from b where id = ?", 2);
Set<String> set = map.keySet();
for (String s : set)
System.out.println(s + ": " + map.get(s));
- queryForList
将查询的数据结果封装到List<Map<String, Object>>集合中,list集合中的每一条数据都为Map<String, Object>集合,就如queryForMap获取到的一条条数据封装到list集合中
List<Map<String, Object>> list = jdbcTemplate.queryForList("select * from b");
for (Map<String, Object> map : list) {
Set<String> set = map.keySet();
for (String s : set)
System.out.print(s + ": " + map.get(s) + " ");
System.out.println();//换行
}
- query
- 实现RowMapper接口的T mapRow(ResultSet resultSet, int i)方法,对查询结果进行手动封装成list集合。
resultSet为sql语句查询数据的结果集
i表示第几行数据,从0开始
List<Student> query = jdbcTemplate.query("select * from b", new RowMapper<Student>() {
@Override
public Student mapRow(ResultSet resultSet, int i) throws SQLException {
Student student = new Student();
student.setId(resultSet.getInt("id"));
student.setName(resultSet.getString("name"));
student.setAge(resultSet.getInt("age"));
student.setSex(resultSet.getString("sex"));
student.setLocal(resultSet.getString("local"));
student.setPhone(resultSet.getString("phone"));
return student;
}
});
这中手动封装的方式和前面的一样的复杂。
- 实现BeanPropertyRowMapper方法自动完成封装,程序会将数据表列名和javaBean的属性名相同的查询数据进行封装。
List<Student> query = jdbcTemplate.query("select * from b", new BeanPropertyRowMapper<Student>(Student.class));
注意:JavaBean中的属性都应该为引用数据类型,因为数据表的数据可能为null,当属性为基本数据类型(int)时不可赋值null,则会出现数据类型转换错误
- queryForObjectbc
将查询对象封装成对象,查询结果有且仅有一条一列
一般使用在聚合函数上
Integer lenght = jdbcTemplate.queryForObject("SELECT COUNT(ID) FROM b", Integer.class);