一. 概述
JdbcTemplate就是Spring对JDBC的封装,目的是使JDBC更加易于使用。JdbcTemplate是Spring的一部分。
JdbcTemplate处理了资源的建立和释放。他帮助我们避免一些常见的错误,比如忘了总要关闭连接。他运行核心的JDBC工作流,如PreparedStatement的建立和执行,而我们只需要提供SQL语句和提取结果。
二.jdbcTemplate核心API
方法 | 作用 |
---|---|
public JdbcTemplate(DataSource dataSource) | 构造方法,传递数据源做为参数 |
int update(String sql, Object…args) | 执行增删改 |
queryForMap() | 返回Map<String,Object>的查询结果,其中键是列名,值是表中对应的记录。 |
queryForObject() | 查询一个对象 |
queryForList() | 返回多条记录的查询结果,封装成一个List集合,但是封装的是Map |
query() | 通用的查询方法,有多个同名方法的重载,可以自定义查询结果集封装成什么样的对象。 |
三.使用jdbcTemplate完成CRUD
1.开发步骤
- 创建项目,导入jar
- 创建jdbcTemplate对象,传入连接池
- 调用execute()、update()、queryXxx()等方法
2.JdbcTemplate实现增删改
API介绍
public int update(String sql, Object ... params); //用于执行`INSERT`、`UPDATE`、`DELETE`等语句。
- 增
@Test
//使用JDBC模版进行添加用户
public void fun01() {
//1.创建jdbcTemplate对象(需要传入连接池)
JdbcTemplate jdbcTemplate = new JdbcTemplate(C3p0Utils.getDataSource());
//2.使用update,执行sql
String sql = "insert into user values(?,?,?,?)";
// Object[] params = {null, "tq", "123456", "田七"};
// jdbcTemplate.update(sql, params);
jdbcTemplate.update(sql, null, "tq", "123456", "田七");
}
- 改
@Test
//使用JDBC模板进行更新用户,把id为7的用户的名字改成ww
public void fun02() {
//1.创建jdbcTemplate对象
JdbcTemplate jdbcTemplate = new JdbcTemplate(C3p0Utils.getDataSource());
//2.使用update,执行sql
// jdbcTemplate.update("UPDATE user set username = 'ww' WHERE id = 7");
String sql = "UPDATE USER set username = ? WHERE id = ?";
Object[] params = {"ww", 7};
jdbcTemplate.update(sql, params);
}
- 删
@Test
//使用JDBC模版进行删除用户
public void fun03() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(C3p0Utils.getDataSource());
jdbcTemplate.update("delete from user where id = ?",7);
}
3. JdbcTemplate实现查询
3.1 查询一条记录封装成Map
- 需求: 查询id为1的用户, 封装成map对象
- 开发步骤:
创建JdbcTemplate对象,传入数据源
编写SQL语句
使用JdbcTemplate对象的==queryForMap(String sql,Object … params)==方法查询结果
返回是一个Map对象
@Test
//查询id为1的用户,封装成map对象
public void fun04() {
//1.创建jdbcTemplate对象(需要传入连接池)
JdbcTemplate jdbcTemplate = new JdbcTemplate(C3p0Utils.getDataSource());
//2.执行queryForMap()的方法来查询
String sql = "SELECT * FROM user WHERE id = ?";
Map<String, Object> map = jdbcTemplate.queryForMap(sql, 1);
System.out.println(map);
}
3.2 查询一条记录封装成实体对象
-
需求: 查询id为1的用户, 封装成user对象
如果每个JavaBean都需要自己封装每个属性,那开发效率将大打折扣,所以Spring JDBC提供了这个接口的实现类BeanPropertyRowMapper,使用起来更加方便。只需要在构造方法中传入User.class类对象即可,它会自动封装所有同名的属性。使用BeanPropertyRowMapper实现类:
-
开发步骤
创建JdbcTemplate对象,传入数据源
编写查询的SQL语句
使用JdbcTemplate对象的queryForObject方法,并传入需要返回的数据的类型
返回是一个实体对象
@Test
// 查询id为1的用户, 封装成user对象
public void fun05() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(C3p0Utils.getDataSource());
String sql = "select * from user WHERE id = ?";
User user = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<>(User.class), 1);
System.out.println(user);
}
3.3 查询多条记录封装成 List<Map<String,Object>>
- 需求: 查询所有的用户, 封装成 List<Map<String,Object>> list
- 开发步骤:
创建JdbcTemplate对象,传入数据源
编写SQL语句
使用JdbcTemplate对象的==queryForList(String sql,Objec…params)==方法查询结果
@Test
// 查询所有的用户, 封装成 List<Map<String,Object>> list
public void fun06() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(C3p0Utils.getDataSource());
String sql = "SELECT * FROM user";
List<Map<String, Object>> mapList = jdbcTemplate.queryForList(sql);
System.out.println(mapList);
}
3.4 查询多条记录封装成 List
- 需求: 查询所有的用户, 封装成 List list
- 开发步骤:
创建JdbcTemplate对象,传入数据源
编写SQL语句
使用JdbcTemplate对象的==query(String sql,new BeanPropertyRowMapper<>,Object … params)==方法查询结果
@Test
// 查询所有的用户, 封装成 List<JavaBean> list
public void fun07() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(C3p0Utils.getDataSource());
String sql = "SELECT * FROM user";
List<User> list = jdbcTemplate.query(sql, new BeanPropertyRowMapper<>(User.class));
System.out.println(list);
}
3.5 统计总记录数
- 需求: 统计user的总记录数
- 开发步骤:
创建JdbcTemplate对象,传入数据源
编写SQL语句
使用JdbcTemplate对象的使用==queryForObject()==方法,指定参数为Integer.class或者Long.class
@Test
//统计user的总记录数
public void fun08() {
JdbcTemplate jdbcTemplate = new JdbcTemplate(C3p0Utils.getDataSource());
String sql = "select COUNT(*) from user ";
Long count = jdbcTemplate.queryForObject(sql, Long.class);
System.out.println(count);
//int count2 = jdbcTemplate.queryForObject(sql, Integer.class);
//System.out.println(count2);
}
4.JDBCTemplate总结
- 创建JDBCTemplate
JdbcTemplate jdbcTemplate = new JdbcTemplate(C3P0Utils.getDataSource());
- 增删改
jdbcTemplate.update(String sql,Object... params);
- 查询
- 查询一条数据,封装成JavaBean对象
jdbcTemplate.queryForObject(String sql,BeanPropertyRowMapper bean,Object... params);
- 查询一条数据,封装成Map对象
jdbcTemplate.queryForMap(String sql,Object... params);
- 统计数量
jdbcTemplate.queryForObject(String sql,Long.class,Object... params);
- 查询多条数据, 封装成List
jdbcTemplate.query(String sql,BeanPropertyRowMapper bean,Object... params);
- 查询多条数据, 封装成List
jdbcTemplate.queryForList(String sql,Object... params);
四.元数据
1.概述
元数据(MetaData),即定义数据的数据。打个比方,就好像我们要想搜索一首歌(歌本身是数据),而我们可以通过歌名,作者,专辑等信息来搜索,那么这些歌名,作者,专辑等等就是这首歌的元数据。因此数据库的元数据就是一些注明数据库信息的数据。
简单来说: 数据库里面元数据就是数据库、表、列的定义信息。
元数据在建立框架和架构方面是特别重要的知识,我们可以使用数据库的元数据来创建自定义JDBC框架, 模仿jdbcTemplate.
-
由PreparedStatement对象的getParameterMetaData ()方法获取的是ParameterMetaData对象。
-
由ResultSet对象的getMetaData()方法获取的是ResultSetMetaData对象。
2. 通过JDBC获得元数据
2.1 ParameterMetaData
ParameterMetaData是由preparedStatement对象通过getParameterMetaData方法获取而来,ParameterMetaData可用于获取有关PreparedStatement对象和其预编译sql语句 中的一些信息. eg:参数个数,获取指定位置占位符的SQL类型
获得ParameterMetaData:
ParameterMetaData parameterMetaData = preparedStatement.getParameterMetaData ()
ParameterMetaData相关的API
- int getParameterCount(); 获得参数个数
- int getParameterType(int param) 获取指定参数的SQL类型。 (注:MySQL不支持获取参数类型)
@Test
//参数元数据
public void fun01() throws Exception {
//1.获得连接
Connection connection = C3p0Utils.getConnection();
//2.创建预编译的sql语句对象
String sql = "SELECT * FROM user WHERE username = ? and password = ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//3.从preparedStatement中获得参数元数据对象
ParameterMetaData parameterMetaData = preparedStatement.getParameterMetaData();
//4.获得参数的个数
System.out.println(parameterMetaData.getParameterCount());
// System.out.println(parameterMetaData.getParameterType(1));//MySQL不支持获取参数类型
}
2.2ResultSetMetaData
ResultSetMetaData是由ResultSet对象通过getMetaData方法获取而来,ResultSetMetaData可用于获取有关ResultSet对象中列的类型和属性的信息。
获得ResultSetMetaData:
ResultSetMetaData resultSetMetaData = resultSet.getMetaData()
resultSetMetaData 相关的API
- getColumnCount(); 获取结果集中列项目的个数
- getColumnName(int column); 获得数据指定列的列名
- getColumnTypeName();获取指定列的SQL类型
- getColumnClassName();获取指定列SQL类型对应于Java的类型
@Test
//结果元数据
public void fun02() throws Exception {
//1.获得连接
Connection connection = C3p0Utils.getConnection();
//2.创建预编译的sql语句对象
String sql = "SELECT * FROM user ";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
//3.执行sql语句,获得ResultSet
ResultSet resultSet = preparedStatement.executeQuery();
//4.创建结果的元数据对象
ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
//获得结果集中列的数量
int columnCount = resultSetMetaData.getColumnCount();
System.out.println(columnCount);
//获得数据指定列的列名
String columnName = resultSetMetaData.getColumnName(2);
System.out.println(columnName);
//获得指定列的sql类型
String columnTypeName = resultSetMetaData.getColumnTypeName(2);
System.out.println(columnTypeName);
//获得指定列sql类型的对应于java的类型
String columnClassName = resultSetMetaData.getColumnClassName(3);
System.out.println(columnClassName);
//列在数据库中的类型(数值编号)
int columnType = resultSetMetaData.getColumnType(1);
System.out.println(columnType);
}
3.自定义JDBC模版
package com.custom;
import com.utils.C3p0Utils;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ParameterMetaData;
import java.sql.PreparedStatement;
public class MyJdbcTemplate {
private DataSource dataSource;
public MyJdbcTemplate(DataSource dataSource) {
this.dataSource = dataSource;
}
/**
* 增删改
* 封装了JDBC操作数据库的步骤+元数据,释放资源(使用者不需要关注释放资源了)
* @param sql
* @param params
* @return
*/
public int update(String sql, Object... params) {
Connection connection = null;
PreparedStatement preparedStatement = null;
try {
//1.非空判断
if (dataSource == null){
throw new RuntimeException("dataSource must not be null...");
}
if (sql == null){
throw new RuntimeException("sql must not be null...");
}
//2.获得连接
connection = dataSource.getConnection();
//3.创建预编译的sql语句对象
preparedStatement = connection.prepareStatement(sql);
//4.获得参数元数据对象
ParameterMetaData parameterMetaData = preparedStatement.getParameterMetaData();
//5.获得参数的个数(?的个数)
int parameterCount = parameterMetaData.getParameterCount();
//6.给每一个?赋值
for (int i = 0; i < parameterCount; i++) {
preparedStatement.setObject(i+1,params[i]);
}
//7.执行
return preparedStatement.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
return -1;
}finally {
C3p0Utils.release(null,preparedStatement,connection);
}
}
}