《SpringBoot 3:入门与应用实战》第 12 章 JDBC 与事务 使用 JdbcTemplate 阅读笔记 31

《SpringBoot 3:入门与应用实战》第 12 章 JDBC 与事务 使用 JdbcTemplate 阅读笔记 31

12.2 使用 JdbcTemplate

整合工作完成后,下面来学习使用 Spring Framework 提供的简化 JDBC 操作的模板类 JdbcTemplate。JdbcTemplate 是 spring-jdbc 包的一个核心类,它提供了一系列简便的 API,屏蔽了操作原生 JDBC 的 API 时编写的模板格式代码。下面先从 JdbcTemplate 的简单 CRUD 开始演示。

12.2.1 基本使用

日常开发中,使用 JdbcTemplate 频率最高的莫过于 CRUD 操作,所以先来学习这一部分内容。在这之前先准备一个实体模型类 User,它跟数据库表中的 tbl_user 对应。

注意,User 类上标注了一个特殊的注解 @Data,这个注解来自一个编译时插件库 Lombok,使用这个工具库可以省略实体类中冗长的getter、setter、toString 等方法,标注 @Data 相当于同时编写了 getter 方法、setter 方法、equals 方法、hashcode 方法、toString 方法,以及当前类的全参数构造方法。要使用 Lombok 库,导入依赖即可,后续的演示代码中将不再采用手动编写的功能型代码,而是由 Lombok 的注解代替。

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>4.1.1</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.yangjunbo</groupId>
    <artifactId>springboot-jdbc-a</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot-jdbc-a</name>
    <description>springboot-jdbc-a</description>
    <url/>
    <licenses>
        <license/>
    </licenses>
    <developers>
        <developer/>
    </developers>
    <scm>
        <connection/>
        <developerConnection/>
        <tag/>
        <url/>
    </scm>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webmvc</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webmvc-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
java 复制代码
package com.yangjunbo.springboot.jdbc;

import lombok.Data;

@Data
public class User {
    private Integer id;
    private String name;
    private String tel;
}

1.insert

对于 insert 操作而言,上面整合 JDBC 时已经使用 execute 方法实现了效果,但是使用 execute 方法有一个严重的问题:这个方法只接受 SQL 语句,无法传入参数,而如果将参数提前整合到 SQL 中,就不能发挥原生 JDBC 的 PreparedStatement 中防 SQL 注入的特性。这么低级的问题 Spring Framework 肯定不会不考虑。

借助 IDE 的代码提示,虽然没有找到 insert 方法,但是找到了一组 update 方法,其中对于倒数第二个方法倍感亲切,刚好能够满足传入参数的需求,所以可以使用该方法完成 insert 操作。

下面在 JdbcTemplateController 中编写一个简单的 insert 操作的代码,像编写原生 JDBC 代码那样声明 SQL 和传参即可。注意这一系列方法的返回值都为 int,代表 DML 语句对数据库影响的行数。

java 复制代码
package com.yangjunbo.springboot.jdbc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JdbcTemplateController {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @GetMapping("/test1")
    public String test1() {
        System.out.println(jdbcTemplate);
        return "success";
    }

    @GetMapping("/test2")
    public String test2() {
        User user = new User();
        user.setName("heihei");
        user.setTel("200");
        int row = jdbcTemplate.update("insert into tbl_user (name, tel) values (?, ?)", user.getName(), user.getTel());
        return "success - " + row;
    }

}

编写完毕后重启工程,随后在浏览器中访问 /test2 路径,接口可以被成功调用,浏览器中显示 "success - 1",代表数据库产生了一条数据的影响。查看 tbl_user 表发现的确又插入了一条数据,证明 insert 语句已经正确执行。

2.update

刚才向 tbl_user 表插入数据时有一个"小失误",不小心将 tel 错当 money 传入,所以需要将名为 heihei 的 tel 属性值修正,下面通过一条 update 语句予以修正。重新编译后访问 /test3 接口,浏览器仍然可以返回 "success - 1" 的信息,查看数据库也发现数据被成功更新。

java 复制代码
package com.yangjunbo.springboot.jdbc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JdbcTemplateController {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @GetMapping("/test1")
    public String test1() {
        System.out.println(jdbcTemplate);
        return "success";
    }

    @GetMapping("/test2")
    public String test2() {
        User user = new User();
        user.setName("heihei");
        user.setTel("200");
        int row = jdbcTemplate.update("insert into tbl_user (name, tel) values (?, ?)", user.getName(), user.getTel());
        return "success - " + row;
    }

    @GetMapping("/test3")
    public String test3() {
        User user = new User();
        user.setName("heihei");
        user.setTel("54321");
        int row = jdbcTemplate.update("update tbl_user set tel = ? where name = ?", user.getTel(), user.getName());
        return "success - " + row;
    }

}

3.delete

最后将这条名为 heihei 的数据删除,发送一条 delete 语句即可。最终可以看到的效果依然是浏览器中显示一条数据被影响,数据库中 id为 5 的数据被删除,只剩下 4 条数据。

java 复制代码
package com.yangjunbo.springboot.jdbc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class JdbcTemplateController {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @GetMapping("/test1")
    public String test1() {
        System.out.println(jdbcTemplate);
        return "success";
    }

    @GetMapping("/test2")
    public String test2() {
        User user = new User();
        user.setName("heihei");
        user.setTel("200");
        int row = jdbcTemplate.update("insert into tbl_user (name, tel) values (?, ?)", user.getName(), user.getTel());
        return "success - " + row;
    }

    @GetMapping("/test3")
    public String test3() {
        User user = new User();
        user.setName("heihei");
        user.setTel("54321");
        int row = jdbcTemplate.update("update tbl_user set tel = ? where name = ?", user.getTel(), user.getName());
        return "success - " + row;
    }

    @GetMapping("/test4")
    public String test4() {
        int row = jdbcTemplate.update("delete from tbl_user where name = ?", "heihei");
        return "success - " + row;
    }

}

4.select

相较于发送 DML 语句而言,发送 DQL 语句(select 语句)的复杂度要高一些。本节先介绍 3 种相对常见的查询场景:查列表、查单条、查数量。

(1) 查列表

对于查询操作,常用的方法名应该是 select 或者 query,好消息是 JdbcTemplate 中的确有名为 query 的方法,但与此同时有一个坏消息,query 系列方法的重载方法多达 45 个。面对如此多的 query 方法,必然要选择一个相对恰当的方法才行。从需求的角度出发,既然查询列表数据的目的是将所有的数据封装到一个集合中,并且能适当附带查询参数,那么可以选择入参带可变参数且返回值为 List 的方法。

读者可能会好奇,RowMapper 是什么?它的作用又是什么?请读者仔细观察它的泛型和方法返回值中List的泛型,可以发现是同一个,这意味着 RowMapper 可以控制查询结果的数据类型。而且从 RowMapper 的源码上看,它可以接受一个 ResultSet 的参数,返回泛型指定的数据类型,这就意味着 RowMapper 的作用就是将封装了查询结果的 ResultSet 转换为指定的目标类型对象。

借助 IDE 可以发现RowMapper 的几个实现类,其中最常用的是 BeanPropertyRowMapper(将结果集转换为实体类对象)、ColumnMapRowMapper(将结果集转换为 Map<String, Object>)和 SingleColumnRowMapper(查询结果为单列的场景下使用)。

通过以上了解,读者可以很容易分辨出,在当前场景中最恰当的 RowMapper 实现类是 BeanPropertyRowMapper。代码展示了一个查询全表数据的示例,只需要写好 SQL 语句并指定 BeanPropertyRowMapper 需要转换的实体类型,即可完成数据查询操作。重新编译代码后访问 /test5 接口,浏览器中可以得到一串 JSON 数据,这些数据与 tbl_user 表的数据一一对应,说明全表数据的查询成功。

java 复制代码
package com.yangjunbo.springboot.jdbc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class JdbcTemplateController {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @GetMapping("/test1")
    public String test1() {
        System.out.println(jdbcTemplate);
        return "success";
    }

    @GetMapping("/test2")
    public String test2() {
        User user = new User();
        user.setName("heihei");
        user.setTel("200");
        int row = jdbcTemplate.update("insert into tbl_user (name, tel) values (?, ?)", user.getName(), user.getTel());
        return "success - " + row;
    }

    @GetMapping("/test3")
    public String test3() {
        User user = new User();
        user.setName("heihei");
        user.setTel("54321");
        int row = jdbcTemplate.update("update tbl_user set tel = ? where name = ?", user.getTel(), user.getName());
        return "success - " + row;
    }

    @GetMapping("/test4")
    public String test4() {
        int row = jdbcTemplate.update("delete from tbl_user where name = ?", "heihei");
        return "success - " + row;
    }

    @GetMapping("/test5")
    public List<User> test5() {
        List<User> userList = jdbcTemplate.query("select * from tbl_user", new BeanPropertyRowMapper<>(User.class));
        return userList;
    }

}

在查询时携带参数也不是难事,选择的这个 query 方法可以在 RowMapper 参数之后继续追加参数,代码演示了只查询 id 大于 2 的数据,代码编写非常简单。

java 复制代码
package com.yangjunbo.springboot.jdbc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class JdbcTemplateController {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @GetMapping("/test1")
    public String test1() {
        System.out.println(jdbcTemplate);
        return "success";
    }

    @GetMapping("/test2")
    public String test2() {
        User user = new User();
        user.setName("heihei");
        user.setTel("200");
        int row = jdbcTemplate.update("insert into tbl_user (name, tel) values (?, ?)", user.getName(), user.getTel());
        return "success - " + row;
    }

    @GetMapping("/test3")
    public String test3() {
        User user = new User();
        user.setName("heihei");
        user.setTel("54321");
        int row = jdbcTemplate.update("update tbl_user set tel = ? where name = ?", user.getTel(), user.getName());
        return "success - " + row;
    }

    @GetMapping("/test4")
    public String test4() {
        int row = jdbcTemplate.update("delete from tbl_user where name = ?", "heihei");
        return "success - " + row;
    }

    @GetMapping("/test5")
    public List<User> test5() {
        List<User> userList = jdbcTemplate.query("select * from tbl_user", new BeanPropertyRowMapper<>(User.class));
        return userList;
    }

    @GetMapping("/test6")
    public List<User> test6() {
        List<User> userList = jdbcTemplate.query("select * from tbl_user where id > ?", new BeanPropertyRowMapper<>(User.class), 2);
        return userList;
    }

}

(2) 查单条

若要查询单条数据,按照思维惯性,JdbcTemplate 应当会提供一个类似 get/getOne/selectOne 等的方法,的确 JdbcTemplate 提供了查询单条数据的方法:queryForObject。但是使用这个系列的方法时需要注意一些问题,下面逐一展开。

对于查询某一条数据,例如按照主键 id 查询,得到的结果要么只有一条数据,要么数据不存在而返回空,那么使用 queryForObject 方法时就仿照上面的 query 方法编写即可。注意,这次没有将 id 直接硬编码,而是使用请求参数的方式传入。

java 复制代码
package com.yangjunbo.springboot.jdbc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class JdbcTemplateController {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @GetMapping("/test1")
    public String test1() {
        System.out.println(jdbcTemplate);
        return "success";
    }

    @GetMapping("/test2")
    public String test2() {
        User user = new User();
        user.setName("heihei");
        user.setTel("200");
        int row = jdbcTemplate.update("insert into tbl_user (name, tel) values (?, ?)", user.getName(), user.getTel());
        return "success - " + row;
    }

    @GetMapping("/test3")
    public String test3() {
        User user = new User();
        user.setName("heihei");
        user.setTel("54321");
        int row = jdbcTemplate.update("update tbl_user set tel = ? where name = ?", user.getTel(), user.getName());
        return "success - " + row;
    }

    @GetMapping("/test4")
    public String test4() {
        int row = jdbcTemplate.update("delete from tbl_user where name = ?", "heihei");
        return "success - " + row;
    }

    @GetMapping("/test5")
    public List<User> test5() {
        List<User> userList = jdbcTemplate.query("select * from tbl_user", new BeanPropertyRowMapper<>(User.class));
        return userList;
    }

    @GetMapping("/test6")
    public List<User> test6() {
        List<User> userList = jdbcTemplate.query("select * from tbl_user where id > ?", new BeanPropertyRowMapper<>(User.class), 2);
        return userList;
    }

    @GetMapping("/test7")
    public User test7(int id) {
        User user = jdbcTemplate.queryForObject("select * from tbl_user where id = ?", new BeanPropertyRowMapper<>(User.class), id);
        return user;
    }

}

按照这种方式查询单条数据可能与预期不同,当传入存在的 id 时可以得到正确的数据,而传入不存在的 id 则会抛出数据不存在的异常EmptyResultDataAccessException,提示 expected 1, actual 0。

如果不希望在数据不存在时抛出异常,则 queryForObject 方法不满足要求,这时需要借助 query 方法先查出 List 集合,再判断集合中是否包含数据,有数据时返回第 0 条数据,而返回空集合时则返回 null。

java 复制代码
package com.yangjunbo.springboot.jdbc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class JdbcTemplateController {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @GetMapping("/test1")
    public String test1() {
        System.out.println(jdbcTemplate);
        return "success";
    }

    @GetMapping("/test2")
    public String test2() {
        User user = new User();
        user.setName("heihei");
        user.setTel("200");
        int row = jdbcTemplate.update("insert into tbl_user (name, tel) values (?, ?)", user.getName(), user.getTel());
        return "success - " + row;
    }

    @GetMapping("/test3")
    public String test3() {
        User user = new User();
        user.setName("heihei");
        user.setTel("54321");
        int row = jdbcTemplate.update("update tbl_user set tel = ? where name = ?", user.getTel(), user.getName());
        return "success - " + row;
    }

    @GetMapping("/test4")
    public String test4() {
        int row = jdbcTemplate.update("delete from tbl_user where name = ?", "heihei");
        return "success - " + row;
    }

    @GetMapping("/test5")
    public List<User> test5() {
        List<User> userList = jdbcTemplate.query("select * from tbl_user", new BeanPropertyRowMapper<>(User.class));
        return userList;
    }

    @GetMapping("/test6")
    public List<User> test6() {
        List<User> userList = jdbcTemplate.query("select * from tbl_user where id > ?", new BeanPropertyRowMapper<>(User.class), 2);
        return userList;
    }

    @GetMapping("/test7")
    public User test7(int id) {
        User user = jdbcTemplate.queryForObject("select * from tbl_user where id = ?", new BeanPropertyRowMapper<>(User.class), id);
        return user;
    }

    @GetMapping("/test8")
    public User test8(int id) {
        List<User> userList = jdbcTemplate.query("select * from tbl_user where id = ?", new BeanPropertyRowMapper<>(User.class), id);
        User user = userList.size() > 0 ? userList.get(0) : null;
        return user;
    }

}

可能有读者会担心,使用 query 方法得到 userList 集合时不需要先判断是否为 null 以避免空指针异常吗?答案是不需要。可以思考JdbcTemplate 底层封装结果集的逻辑,当得到 ResultSet 时,无论其中是否包含数据,至少应当有代码所示的伪代码逻辑。按照该逻辑,显然即便 ResultSet 中没有数据,List 集合也已经被创建,它不可能为 null,所以得到 userList 对象时可以直接调用其 size 方法去做判断,而无须考虑空指针异常的问题。

java 复制代码
 List<T> list = new ArrayList<>();
 while(resultSet.next()) {
     T t = new T();
     t.setXXX(resultSet.getString(XXX));
     list.add(t);
 }
 return list;

另外请读者注意一个细节,queryForObject 方法的重载方法中有一组方法,它们的第二个参数可以传入一个 Class 类型,但是这并不意味着可以直接传入 User.clas s代替 BeanPropertyRowMapper。可以简单编写代码测试一下,代码中将 queryForObject 方法的第二个参数设置为 User.class,重新编译代码后访问 /test9 接口,发现程序抛出了不正确的结果集列数异常IncorrectResultSetColumnCountException,它期望只得到一列数据,而编写的 SQL 语句执行后返回了 3 列数据,由此可以得知,当queryForObject 方法的第二个参数传入 Class 类型时,需要保证 SQL 语句的查询结果只能有一列数据,而传入的 Class 类型也需要跟查询列的数据类型相对应。

java 复制代码
package com.yangjunbo.springboot.jdbc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class JdbcTemplateController {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @GetMapping("/test1")
    public String test1() {
        System.out.println(jdbcTemplate);
        return "success";
    }

    @GetMapping("/test2")
    public String test2() {
        User user = new User();
        user.setName("heihei");
        user.setTel("200");
        int row = jdbcTemplate.update("insert into tbl_user (name, tel) values (?, ?)", user.getName(), user.getTel());
        return "success - " + row;
    }

    @GetMapping("/test3")
    public String test3() {
        User user = new User();
        user.setName("heihei");
        user.setTel("54321");
        int row = jdbcTemplate.update("update tbl_user set tel = ? where name = ?", user.getTel(), user.getName());
        return "success - " + row;
    }

    @GetMapping("/test4")
    public String test4() {
        int row = jdbcTemplate.update("delete from tbl_user where name = ?", "heihei");
        return "success - " + row;
    }

    @GetMapping("/test5")
    public List<User> test5() {
        List<User> userList = jdbcTemplate.query("select * from tbl_user", new BeanPropertyRowMapper<>(User.class));
        return userList;
    }

    @GetMapping("/test6")
    public List<User> test6() {
        List<User> userList = jdbcTemplate.query("select * from tbl_user where id > ?", new BeanPropertyRowMapper<>(User.class), 2);
        return userList;
    }

    @GetMapping("/test7")
    public User test7(int id) {
        User user = jdbcTemplate.queryForObject("select * from tbl_user where id = ?", new BeanPropertyRowMapper<>(User.class), id);
        return user;
    }

    @GetMapping("/test8")
    public User test8(int id) {
        List<User> userList = jdbcTemplate.query("select * from tbl_user where id = ?", new BeanPropertyRowMapper<>(User.class), id);
        User user = userList.size() > 0 ? userList.get(0) : null;
        return user;
    }

    @GetMapping("/test9")
    public User test9(int id) {
        User user = jdbcTemplate.queryForObject("select * from tbl_user where id = ?", User.class, id);
        return user;
    }
}

值得一提的是,这个异常由 SingleColumnRowMapper 抛出,说明当指定 Class 类型时,JdbcTemplate 会选用SingleColumnRowMapper 封装数据,这也解释了为什么它的预期只有一列数据。

(3) 查数量

既然 queryForObject 方法在指定 Class 时只能查询一列数据,那么这个方法的返回值必定只有一行一列,即一个数据值,这种查询场景中最典型的就是 SQL 中的 COUNT 查询,即查询数据行数。SQL 中查询数据行数通常可以使用 Integer 或 Long 接收,代码演示了使用 Integer 接收的效果。重新编译代码后访问 /test10 接口,可以在浏览器中看到 5,与 tbl_user 表中的数据行数吻合,证明queryForObject 发送 COUNT 查询成功。

java 复制代码
package com.yangjunbo.springboot.jdbc;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
public class JdbcTemplateController {
    
    @Autowired
    private JdbcTemplate jdbcTemplate;
    
    @GetMapping("/test1")
    public String test1() {
        System.out.println(jdbcTemplate);
        return "success";
    }

    @GetMapping("/test2")
    public String test2() {
        User user = new User();
        user.setName("heihei");
        user.setTel("200");
        int row = jdbcTemplate.update("insert into tbl_user (name, tel) values (?, ?)", user.getName(), user.getTel());
        return "success - " + row;
    }

    @GetMapping("/test3")
    public String test3() {
        User user = new User();
        user.setName("heihei");
        user.setTel("54321");
        int row = jdbcTemplate.update("update tbl_user set tel = ? where name = ?", user.getTel(), user.getName());
        return "success - " + row;
    }

    @GetMapping("/test4")
    public String test4() {
        int row = jdbcTemplate.update("delete from tbl_user where name = ?", "heihei");
        return "success - " + row;
    }

    @GetMapping("/test5")
    public List<User> test5() {
        List<User> userList = jdbcTemplate.query("select * from tbl_user", new BeanPropertyRowMapper<>(User.class));
        return userList;
    }

    @GetMapping("/test6")
    public List<User> test6() {
        List<User> userList = jdbcTemplate.query("select * from tbl_user where id > ?", new BeanPropertyRowMapper<>(User.class), 2);
        return userList;
    }

    @GetMapping("/test7")
    public User test7(int id) {
        User user = jdbcTemplate.queryForObject("select * from tbl_user where id = ?", new BeanPropertyRowMapper<>(User.class), id);
        return user;
    }

    @GetMapping("/test8")
    public User test8(int id) {
        List<User> userList = jdbcTemplate.query("select * from tbl_user where id = ?", new BeanPropertyRowMapper<>(User.class), id);
        User user = userList.size() > 0 ? userList.get(0) : null;
        return user;
    }

    @GetMapping("/test9")
    public User test9(int id) {
        User user = jdbcTemplate.queryForObject("select * from tbl_user where id = ?", User.class, id);
        return user;
    }

    @GetMapping("/test10")
    public Integer test10() {
        Integer count = jdbcTemplate.queryForObject("select count(*) from tbl_user", Integer.class);
        return count;
    }

}
相关推荐
torpidcat1 小时前
ruoyi-vue-pro 若依芋道 java springboot +mybatis 生日查询相关
java·vue.js·spring boot
金字塔頂の蝸牛2 小时前
商务日语口语全手册(一)
笔记·日语·语言·外语
Zeaon2 小时前
别再手写筛选栏了:一个可组合的 Flutter 选择组件(5 入口 × 7 委托)
android·flutter
从零开始的嵌入式之旅2 小时前
day36
linux·c语言·经验分享·笔记·嵌入式硬件
Michaelwubo2 小时前
mysql8 主从 HA切换
android·adb
墨狂之逸才2 小时前
Android 工业手持机蓝牙扫描失败:为什么同时需要蓝牙和定位权限
android
xcl09252 小时前
智慧场馆解决方案系统源码:从架构设计到部署实战
java·spring boot
黑马程序员毕设3 小时前
基于Java的仪器管理系统设计与实现
java·开发语言·spring boot·后端·微信小程序
骇客野人3 小时前
SpringBoot电商购物车、结算、下单、库存方案设计与落地实施步骤
java·spring boot·后端