【愚公系列】2023年05月 Java教学课程 114-JDBC的(JDBCTemplate)
一、JDBC框架(JDBCTemplate)
1.JDBCTemplate的概念
JDBCTemplate是Spring Framework中的一个类,它简化了JDBC(Java数据库连接)的使用。它提供了一组用于执行常见数据库操作的方法,如插入、更新、删除和查询数据,而不需要样板代码。
JDBCTemplate类是Spring JDBC模块的中心组件,它被设计为与任何JDBC兼容的数据库一起工作。它在JDBC API上提供了更高级别的抽象,减少了执行常见数据库操作所需的代码量。
与使用原始JDBC相比,JDBCTemplate提供了几个好处,包括:
• 简化的样板代码:JDBCTemplate处理JDBC的低级细节,如打开和关闭连接、创建语句和管理事务。这减少了执行数据库操作所需的样板代码的数量。
• 提高了可读性:JDBCTemplate提供了一个简化的API,比原始JDBC代码更容易阅读和理解。
• 提高了可维护性:JDBCTemplate提供了一个一致且易于使用的API,使其更容易随着时间的推移维护数据库代码。
• 更好的错误处理:与原始JDBC相比,JDBCTemplate提供了更出色的错误处理功能,使开发人员能够更轻松有效地处理异常。
总的来说,JDBCTemplate是一个强大的Java数据库处理工具,它提供了一个简单一致的API,减少了执行常见数据库操作所需的样板代码量。
2.自定义JDBC框架
2.1数据库的源信息
• DataBaseMetaData(了解):数据库的源信息
– java.sql.DataBaseMetaData:封装了整个数据库的综合信息
– 例如:
• String getDatabaseProductName():获取数据库产品的名称
• int getDatabaseProductVersion():获取数据库产品的版本号
• ParameterMetaData:参数的源信息
– java.sql.ParameterMetaData:封装的是预编译执行者对象中每个参数的类型和属性
– 这个对象可以通过预编译执行者对象中的getParameterMetaData()方法来获取
– 核心功能:
• int getParameterCount():获取sql语句中参数的个数
• ResultSetMetaData:结果集的源信息
– java.sql.ResultSetMetaData:封装的是结果集对象中列的类型和属性
– 这个对象可以通过结果集对象中的getMetaData()方法来获取
– 核心功能:
• int getColumnCount():获取列的总数
• String getColumnName(int i):获取列名
2.2JDBCTemplate类增删改功能的编写
public class JDBCTemplate {
private DataSource dataSource;
private Connection con;
private PreparedStatement pst;
private ResultSet rs;
public JDBCTemplate(DataSource dataSource) {
this.dataSource = dataSource;
}
//专用于执行增删改sql语句的方法
public int update(String sql,Object...objs) {
int result = 0;
try{
con = dataSource.getConnection();
pst = con.prepareStatement(sql);
//获取sql语句中的参数源信息
ParameterMetaData pData = pst.getParameterMetaData();
//获取sql语句中参数的个数
int parameterCount = pData.getParameterCount();
//判断参数个数是否一致
if(parameterCount != objs.length) {
throw new RuntimeException("参数个数不匹配");
}
//为sql语句中的?占位符赋值
for (int i = 0; i < objs.length; i++) {
pst.setObject(i+1,objs[i]);
}
//执行sql语句
result = pst.executeUpdate();
} catch(Exception e) {
e.printStackTrace();
} finally {
//释放资源
DataSourceUtils.close(con,pst);
}
//返回结果
return result;
}
}
2.3JDBCTemplate类查询功能的编写
• 实体类
/*
学生实体类
*/
public class Student {
private Integer sid;
private String name;
private Integer age;
private Date birthday;
public Student() {
}
public Student(Integer sid, String name, Integer age, Date birthday) {
this.sid = sid;
this.name = name;
this.age = age;
this.birthday = birthday;
}
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
@Override
public String toString() {
return "Student{" +
"sid=" + sid +
", name='" + name + '\'' +
", age=" + age +
", birthday=" + birthday +
'}';
}
}
• ResultSetHandler接口
/*
用于处理结果集的接口
*/
public interface ResultSetHandler<T> {
//处理结果集的抽象方法。
<T> T handler(ResultSet rs);
}
• BeanHandler实现类
/*
实现类1:用于完成将查询出来的一条记录,封装到Student对象中
*/
public class BeanHandler<T> implements ResultSetHandler<T> {
//1.声明对象类型变量
private Class<T> beanClass;
//2.有参构造对变量赋值
public BeanHandler(Class<T> beanClass) {
this.beanClass = beanClass;
}
/*
将ResultSet结果集中的数据封装到beanClass类型对象中
*/
@Override
public T handler(ResultSet rs) {
//3.声明对象
T bean = null;
try{
//4.创建传递参数的对象
bean = beanClass.newInstance();
//5.判断是否有结果集
if(rs.next()) {
//6.得到所有的列名
//6.1先得到结果集的源信息
ResultSetMetaData rsmd = rs.getMetaData();
//6.2还要得到有多少列
int columnCount = rsmd.getColumnCount();
//6.3遍历列数
for(int i = 1; i <= columnCount; i++) {
//6.4得到每列的列名
String columnName = rsmd.getColumnName(i);
//6.5通过列名获取数据
Object columnValue = rs.getObject(columnName);
//6.6列名其实就是对象中成员变量的名称。于是就可以使用列名得到对象中属性的描述器(get和set方法)
PropertyDescriptor pd = new PropertyDescriptor(columnName.toLowerCase(),beanClass);
//6.7获取set方法
Method writeMethod = pd.getWriteMethod();
//6.8执行set方法,给成员变量赋值
writeMethod.invoke(bean,columnValue);
}
}
} catch (Exception e) {
e.printStackTrace();
}
//7.将对象返回
return bean;
}
}
• BeanListHandler实现类
/*
实现类2:用于将结果集封装到集合中
*/
public class BeanListHandler<T> implements ResultSetHandler<T> {
//1.声明对象变量
private Class<T> beanClass;
//2.有参构造为变量赋值
public BeanListHandler(Class<T> beanClass) {
this.beanClass = beanClass;
}
@Override
public List<T> handler(ResultSet rs) {
//3.创建集合对象
List<T> list = new ArrayList<>();
try{
//4.遍历结果集对象
while(rs.next()) {
//5.创建传递参数的对象
T bean = beanClass.newInstance();
//6.得到所有的列名
//6.1先得到结果集的源信息
ResultSetMetaData rsmd = rs.getMetaData();
//6.2还要得到有多少列
int columnCount = rsmd.getColumnCount();
//6.3遍历列数
for(int i = 1; i <= columnCount; i++) {
//6.4得到每列的列名
String columnName = rsmd.getColumnName(i);
//6.5通过列名获取数据
Object columnValue = rs.getObject(columnName);
//6.6列名其实就是对象中成员变量的名称。于是就可以使用列名得到对象中属性的描述器(get和set方法)
PropertyDescriptor pd = new PropertyDescriptor(columnName.toLowerCase(),beanClass);
//6.7获取set方法
Method writeMethod = pd.getWriteMethod();
//6.8执行set方法,给成员变量赋值
writeMethod.invoke(bean,columnValue);
}
//7.将对象保存到集合中
list.add(bean);
}
} catch (Exception e) {
e.printStackTrace();
}
//8.返回结果
return list;
}
}
• ScalarHandler实现类
/*
实现类3:用于返回一个聚合函数的查询结果
*/
public class ScalarHandler<T> implements ResultSetHandler<T> {
@Override
public Long handler(ResultSet rs) {
//1.声明一个变量
Long value = null;
try{
//2.判断是否有结果
if(rs.next()) {
//3.获取结果集的源信息
ResultSetMetaData rsmd = rs.getMetaData();
//4.获取第一列的列名
String columnName = rsmd.getColumnName(1);
//5.根据列名获取值
value = rs.getLong(columnName);
}
} catch(Exception e) {
e.printStackTrace();
}
//6.将结果返回
return value;
}
}
• JDBCTemplate类
public class JDBCTemplate {
private DataSource dataSource;
private Connection con;
private PreparedStatement pst;
private ResultSet rs;
public JDBCTemplate(DataSource dataSource) {
this.dataSource = dataSource;
}
/*
专用于执行聚合函数sql语句的方法
*/
public Long queryForScalar(String sql, ResultSetHandler<Long> rsh, Object...objs) {
Long result = null;
try{
con = dataSource.getConnection();
pst = con.prepareStatement(sql);
//获取sql语句中的参数源信息
ParameterMetaData pData = pst.getParameterMetaData();
int parameterCount = pData.getParameterCount();
//判断参数个数是否一致
if(parameterCount != objs.length) {
throw new RuntimeException("参数个数不匹配");
}
//为sql语句中的?占位符赋值
for (int i = 0; i < objs.length; i++) {
pst.setObject(i+1,objs[i]);
}
//执行sql语句
rs = pst.executeQuery();
//通过ScalarHandler方式对结果进行处理
result = rsh.handler(rs);
} catch(Exception e) {
e.printStackTrace();
} finally {
//释放资源
DataSourceUtils.close(con,pst,rs);
}
//将结果返回
return result;
}
/*
专用于查询所有记录sql语句的方法
*/
public <T> List<T> queryForList(String sql, ResultSetHandler<T> rsh, Object...objs) {
List<T> list = new ArrayList<>();
try{
con = dataSource.getConnection();
pst = con.prepareStatement(sql);
//获取sql语句中的参数源信息
ParameterMetaData pData = pst.getParameterMetaData();
int parameterCount = pData.getParameterCount();
//判断参数个数是否一致
if(parameterCount != objs.length) {
throw new RuntimeException("参数个数不匹配");
}
//为sql语句中的?占位符赋值
for (int i = 0; i < objs.length; i++) {
pst.setObject(i+1,objs[i]);
}
//执行sql语句
rs = pst.executeQuery();
//通过BeanListHandler方式对结果进行处理
list = rsh.handler(rs);
} catch(Exception e) {
e.printStackTrace();
} finally {
//释放资源
DataSourceUtils.close(con,pst,rs);
}
//将结果返回
return list;
}
/*
专用于执行查询一条记录sql语句的方法
*/
public <T> T queryForObject(String sql, ResultSetHandler<T> rsh, Object...objs) {
T obj = null;
try{
con = dataSource.getConnection();
pst = con.prepareStatement(sql);
//获取sql语句中的参数源信息
ParameterMetaData pData = pst.getParameterMetaData();
int parameterCount = pData.getParameterCount();
//判断参数个数是否一致
if(parameterCount != objs.length) {
throw new RuntimeException("参数个数不匹配");
}
//为sql语句中的?占位符赋值
for (int i = 0; i < objs.length; i++) {
pst.setObject(i+1,objs[i]);
}
//执行sql语句
rs = pst.executeQuery();
//通过BeanHandler方式对结果进行处理
obj = rsh.handler(rs);
} catch(Exception e) {
e.printStackTrace();
} finally {
//释放资源
DataSourceUtils.close(con,pst,rs);
}
//将结果返回
return obj;
}
}
2.4测试自定义JDBC框架的使用
public class JDBCTemplateTest {
//创建JDBCTemplate对象
JDBCTemplate template = new JDBCTemplate(DataSourceUtils.getDataSource());
@Test
public void selectScalar() {
//查询student表的记录条数
String sql = "SELECT COUNT(*) FROM student";
Long count = template.queryForScalar(sql, new ScalarHandler<Long>());
System.out.println(count);
}
@Test
public void selectAll() {
//查询所有学生信息
String sql = "SELECT * FROM student";
List<Student> list = template.queryForList(sql, new BeanListHandler<Student>(Student.class));
for(Student stu : list) {
System.out.println(stu);
}
}
@Test
public void selectOne() {
//查询张三这条记录
String sql = "SELECT * FROM student WHERE sid=?";
//通过BeanHandler将结果封装成一个Student对象
Student stu = template.queryForObject(sql, new BeanHandler<Student>(Student.class), 1);
System.out.println(stu);
}
@Test
public void insert() {
//新增周七记录
String sql = "INSERT INTO student VALUES (?,?,?,?)";
Object[] params = {5,"周七",27,"2007-07-07"};
int result = template.update(sql, params);
System.out.println(result);
}
@Test
public void delete() {
//删除周七这条记录
String sql = "DELETE FROM student WHERE sid=?";
int result = template.update(sql, 5);
System.out.println(result);
}
@Test
public void update() {
//修改张三的年龄为33
String sql = "UPDATE student SET age=? WHERE name=?";
Object[] params = {33,"张三"};
int result = template.update(sql,params);
System.out.println(result);
}
}
- 点赞
- 收藏
- 关注作者
评论(0)