从01开始 从01开始
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)

peterjxl

人生如逆旅,我亦是行人
首页
  • 计算机科学导论
  • 数字电路
  • 计算机组成原理

    • 计算机组成原理-北大网课
  • 操作系统
  • Linux
  • Docker
  • 计算机网络
  • 计算机常识
  • Git
  • JavaSE
  • Java高级
  • JavaEE

    • Ant
    • Maven
    • Log4j
    • Junit
    • JDBC
    • XML-JSON
  • JavaWeb

    • 服务器软件
    • Servlet
  • Spring
  • 主流框架

    • Redis
    • Mybatis
    • Lucene
    • Elasticsearch
    • RabbitMQ
    • MyCat
    • Lombok
  • SpringMVC
  • SpringBoot
  • 学习网课的心得
  • 输入法
  • 节假日TodoList
  • 其他
  • 关于本站
  • 网站日记
  • 友人帐
  • 如何搭建一个博客
GitHub (opens new window)
  • JavaSE

  • JavaSenior

  • JavaEE

    • JavaEE概念

    • Ant

    • Maven

    • 日志

    • Junit

    • JDBC

      • 什么是JDBC
      • JDBC连接、查询和更新
      • JDBC连接字符串
      • JDBC常用类介绍
      • PreparedStatement是如何防止SQL注入的
      • ResultSet结果封装为对象
      • JDBC工具类
      • JDBC更新
      • JDBC事务和批量
      • JDBC连接池
      • JDBCTemplate
        • JDBC存在的问题
        • 使用JDBCTemplate
        • queryForMap​:查询一条数据并封装
        • queryForList​:封装为list集合
        • query​​​:封装对象
        • queryForObject​:查询总记录数
        • 总结
      • JDBC
    • XML和JSON

    • Java
  • JavaWeb

  • Spring

  • 主流框架

  • SpringMVC

  • SpringBoot

  • Java并发

  • Java源码

  • JVM

  • 韩顺平

  • Java
  • Java
  • JavaEE
  • JDBC
2023-03-24
目录

JDBCTemplate

# 40.JDBCTemplate

JDBC Template是用来简化我们的代码的。例如我们只关心SQL怎么写,怎么执行,但是封装为对象的时候要一个个手工封装,非常麻烦。

# JDBC存在的问题

即使我们使用了连接池和工具类,可以很方便地获取连接、释放连接。

但是在操作数据库时还是存在问题:每一次操作数据库(增删改查),都要定义SQL,设置参数,执行操作,处理结果;特别是处理结果这里非常麻烦,要一步步地封装为对象(参考ResultSet结果封装为对象的时候)。

其实我们应该只关心SQL怎么写,怎么封装成对象,这纯粹是体力活,没什么技术含量。为此,有个叫Spring的框架对JDBC做了简单的封装,提供了一个JDBCTemplate对象简化JDBC的开发。

‍

‍

# 使用JDBCTemplate

这里先整体说下使用步骤:

  • 导入jar包

  • 创建JdbcTemplate对象,依赖于数据源DataSource:JdbcTemplate template = new JdbcTemplate(ds);​

  • 调用JdbcTemplate​的方法来完成CRUD的操作:

    • update()​ :执行DML语句。增、删、改语句

    • queryForMap()​:查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合。注意:这个方法查询的结果集长度只能是1

    • queryForList()​:查询结果将结果集封装为list集合。注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

    • query()​:查询结果,将结果封装为JavaBean对象。query的参数:RowMapper

      • 一般我们使用BeanPropertyRowMapper实现类。可以完成数据到JavaBean的自动封装
      • new BeanPropertyRowMapper<类型>(类型.class)
    • queryForObject​:查询结果,将结果封装为对象。一般用于聚合函数的查询

‍

‍

# 导入依赖

‍

总共需要5个jar包:

commons-logging-1.2.jar
spring-beans-5.0.0.RELEASE.jar
spring-core-5.0.0.RELEASE.jar
spring-jdbc-5.0.0.RELEASE.jar
spring-tx-5.0.0.RELEASE.jar

‍

可以从我的GitHub仓库里下载 jar包:

Gitee:lib · /LearnJavaEE - Gitee (opens new window)

GitHub:LearnJavaEE/lib at master · Peter-JXL/LearnJavaEE (opens new window)

或者去官网Spring | Home (opens new window)下载。

‍

# JdbcTemplate基本使用

举个例子,我们要更新一个SQL,可以这样做:

JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSourse());
String sql = "update students set name = ? where id = ?";
int count = template.update(sql, "PeterJXL", 1);
System.out.println(count);
1
2
3
4

我们不用再申请和释放连接了!我们只需要关心SQL语句怎么写,怎么赋值。

懂得JdbcTemplate的基本使用后,我们做一些练习:

  1. 修改1号学生的 name 为 caixukun
  2. 添加一条记录
  3. 删除刚才添加的记录
  4. 查询id为1的记录,将其封装为Map集合
  5. 查询所有记录,将其封装为List
  6. 查询所有记录,将其封装为Student对象的List集合(Student类我们在ResultSet结果封装为对象创建过了,这里不再赘述)
  7. 查询总记录数

每个小点我们用一个方法来完成,由于要测试的方法比较多,我们使用Junit框架

‍

# JdbcTemplate执行DML语句

这里先演示前3个方法:

  1. 修改1号学生的 name 为 caixukun
  2. 添加一条记录
  3. 删除刚才添加的记录
package chapter2JDBC;

import org.junit.Test;
import org.springframework.jdbc.core.JdbcTemplate;
import java.sql.*;

public class JDBCDemo17TemplateDML {

    private JdbcTemplate template = new JdbcTemplate(DruidUtils.getDataSourse());

    @Test
    public void testUpdateStuname(){
        String sql = "update students set name = ? where id = ?";
        int caixukun = template.update(sql, "caixukun", 1);
        System.out.println(caixukun);
    }

    @Test
    public void testInsertStu(){
        String sql = "insert into students (id, grade, name, gender, score) values (?, ?,?,?,?)";
        int caixukun = template.update(sql, 666, 1, "caixukun", 1, 99);
        System.out.println(caixukun);
    }

    @Test
    public void testDelStu(){
        String sql = "delete from students where id = ?";
        int count = template.update(sql,666);
        System.out.println(count);
    }
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

‍

‍

‍

‍

# JdbcTemplate执行DQL语句

继续完成以下练习:

  1. 查询id为1的记录,将其封装为Map集合
  2. 查询所有记录,将其封装为List
  3. 查询所有记录,将其封装为Student对象的List集合(Student类我们在ResultSet结果封装为对象创建过了,这里不再赘述)
  4. 查询总记录数

‍

# queryForMap​:查询一条数据并封装

​queryForMap()​:查询结果将结果集封装为map集合,将列名作为key,将值作为value 将这条记录封装为一个map集合。注意:这个方法查询的结果集长度只能是1

  @Test
    public void testSelect1(){
        String sql = "select * from students where id = ?";
        Map<String, Object> stringObjectMap = template.queryForMap(sql, 1);
        System.out.println(stringObjectMap);
    }
1
2
3
4
5
6

‍

运行结果:

{id=1, name=caixukun, gender=true, grade=1, score=88}
1

‍

注意:queryForMap()​只能封装一条数据的情况,如果有多条数据或者0条,则会报错,假设我们这样写:

String sql = "select * from students";
Map<String, Object> stringObjectMap = template.queryForMap(sql);
System.out.println(stringObjectMap);
1
2
3

运行结果:


org.springframework.dao.IncorrectResultSizeDataAccessException: Incorrect result size: expected 1, actual 13
......
1
2
3

‍

# queryForList​:封装为list集合

​queryForList()​:查询结果将结果集封装为list集合。注意:将每一条记录封装为一个Map集合,再将Map集合装载到List集合中

public void testSelect1(){
        String sql = "select * from students where id = ?";
        Map<String, Object> stringObjectMap = template.queryForMap(sql, 1);
        System.out.println(stringObjectMap);
    }
1
2
3
4
5

‍

运行结果:

{id=1, name=caixukun, gender=true, grade=1, score=88}
{id=2, name=小红, gender=true, grade=1, score=95}
{id=3, name=小军, gender=false, grade=1, score=93}
{id=4, name=小白, gender=false, grade=1, score=100}
{id=5, name=小牛, gender=true, grade=2, score=96}
{id=6, name=小兵, gender=true, grade=2, score=99}
{id=7, name=小强, gender=false, grade=2, score=86}
{id=8, name=小乔, gender=false, grade=2, score=79}
{id=9, name=小青, gender=true, grade=3, score=85}
{id=10, name=小王, gender=true, grade=3, score=90}
{id=11, name=小林, gender=false, grade=3, score=91}
{id=12, name=小贝, gender=false, grade=3, score=77}
{id=1011, name=caixukun, gender=true, grade=1, score=99}
1
2
3
4
5
6
7
8
9
10
11
12
13

‍

# query​​​:封装对象

​query()​:查询结果,将结果封装为JavaBean对象。query的参数:RowMapper对象

  • 一般我们使用BeanPropertyRowMapper实现类,可以完成数据到JavaBean的自动封装。
  • 例如:new BeanPropertyRowMapper<类型>(类型.class)

‍

我们自己实现RowMapper匿名内部类的方法来实现数据到对象的封装:

@Test
public void testQuery(){
    String sql = "select * from students ";
    List<Student> stus = template.query(sql, new RowMapper<Student>() {
        @Override
        public Student mapRow(ResultSet rs, int i) throws SQLException {
            Student stu = new Student();
            int id = rs.getInt("id");

            String name = rs.getString("name");
            int gender = rs.getInt("gender");
            int grade = rs.getInt("grade");
            int score = rs.getInt("score");
            stu.setId(id);
            stu.setName(name);
            stu.setGender(gender);
            stu.setGrade(grade);
            stu.setScore(score);
            return stu;
        }
    });

    for (Student stu : stus) {
        System.out.println(stu);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

‍

但这样好像并没简化多少代码?我们之前也是这样写的。先别急,我们可以用默认的实现类,而不是自己实现RowMapper匿名内部类,简化了大量的代码:

 @Test
public void testQuery2(){
    String sql = "select * from students ";
    List<Student> stus = template.query(sql, new BeanPropertyRowMapper<>(Student.class));
    for (Student stu : stus) {
        System.out.println(stu);
    }
}
1
2
3
4
5
6
7
8

‍

我们来看看BeanPropertyRowMapper​的源码:可以看到BeanPropertyRowMapper​已经实现了RowMapper接口。

public class BeanPropertyRowMapper<T> implements RowMapper<T> {
1

‍

‍

‍

# queryForObject​:查询总记录数

queryForObject​:查询结果,将结果封装为对象。一般用于聚合函数的查询

‍

@Test
public void testQuerySum(){
    String sql = "select count(id) from students ";
    Long aLong = template.queryForObject(sql, Long.class);
    System.out.println(aLong);
}
1
2
3
4
5
6

第二个参数的意思是,返回的类型要用什么类型来接受,这里我们用Long。

‍

‍

# 总结

使用JDBCTemplate,可以大大简化我们的代码,我们只需关心SQL怎么写。

在GitHub上编辑此页 (opens new window)
上次更新: 2023/3/30 09:46:17
JDBC连接池
JDBC

← JDBC连接池 JDBC→

Theme by Vdoing | Copyright © 2022-2023 粤ICP备2022067627号-1 粤公网安备 44011302003646号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式