【愚公系列】2023年05月 Java教学课程 114-JDBC的(JDBCTemplate)

举报
愚公搬代码 发表于 2023/05/31 22:22:22 2023/05/31
【摘要】 一、JDBC框架(JDBCTemplate)1.JDBCTemplate的概念JDBCTemplate是Spring Framework中的一个类,它简化了JDBC(Java数据库连接)的使用。它提供了一组用于执行常见数据库操作的方法,如插入、更新、删除和查询数据,而不需要样板代码。JDBCTemplate类是Spring JDBC模块的中心组件,它被设计为与任何JDBC兼容的数据库一起工作...

一、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);
}
}


【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。