Spring Boot 3.2 新特性:JdbcClient

小哈学Java

共 10468字,需浏览 21分钟

 ·

2024-07-29 15:30

来源:springcamp.cn/spring-boot-jdbc-client/

👉 欢迎加入小哈的星球,你将获得: 专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;

截止目前,累计输出 50w+ 字,讲解图 2200+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有1800+小伙伴加入

  • 一、概述
  • 二、引入 JdbcClient
  • 三、查询操作
  • 四、插入数据
  • 五、总结
图片

SpringBoot 3.2引入了新的 JdbcClient 用于数据库操作,JdbcClient对JdbcTemplate进行了封装,采用了 fluent API 的风格,可以进行链式调用。

自此,spring自带的数据库操作有了4种方式:JdbcTemplate、JdbcClient、SpringDataJdbc、SpringDataJpa。

对于不适合使用复杂的ORM框架,或者需要编写复杂的SQL的场景,可以使用JdbcClient自己编写SQL来操作数据库。不过JdbcClient不支持数据的批量操作和存储过程调用,对于这种情况就需要使用JdbcTemplate。

具体的代码参照示例项目:https://github.com/qihaiyan/springcamp/tree/master/spring-data-jdbc-client

一、概述

JdbcClient是一个轻量的数据库操作框架,采用 fluent API 风格,简单灵活,易于阅读和维护,支持编写复杂的SQL。

二、引入 JdbcClient

首先引入 spring-data-jdbc 依赖。

在 build.gradle 中增加一行代码:

implementation 'org.springframework.boot:spring-boot-starter-data-jdbc'

在Service中直接注入JdbcClient即可:

@Component
public class DbService {
    @Autowired
    private JdbcClient jdbcClient;
}

三、查询操作

通过JdbcClient,可以按照主键查数据,也可以按照自定义查询条件查数据。

按照主键查数据:

public MyData findDataById(Long id) {
        return jdbcClient.sql("select * from my_data where id = ?")
                .params(id)
                .query(MyData.class)
                .single();
    }

按照自定义查询条件查数据:

public List<MyData> findDataByName(String name) {
        return jdbcClient.sql("select * from my_data where name = ?")
                .params(name)
                .query(MyData.class)
                .list();
    }

以上两种查询方式,查询条件中的变量使用的是占位符,JdbcClient也支持按照参数名进行查询:

public Integer insertDataWithNamedParam(MyData myData) {
        Integer rowsAffected = jdbcClient.sql("insert into my_data values(:id,:name) ")
                .param("id", myData.id())
                .param("name", myData.name())
                .update();
        return rowsAffected;
    }

当参数比较多时,可以将参数放到一个Map中,用Map进行查询:

public List<MyData> findDataByParamMap(Map<String, ?> paramMap) {
        return jdbcClient.sql("select * from my_data where name = :name")
                .params(paramMap)
                .query(MyData.class)
                .list();
    }

当查询返回的结果不能简单的映射到一个类时,可以编写RowMapper,适用于SQL语句比较复杂的场景:

public List<MyData> findDataWithRowMapper() {
        return jdbcClient.sql("select * from my_data")
                .query((rs, rowNum) -> new MyData(rs.getLong("id"), rs.getString("name")))
                .list();
    }

同时也支持查询记录数:

public Integer countByName(String name) {
        return jdbcClient.sql("select count(*) from my_data where name = ?")
                .params(name)
                .query(Integer.class)
                .single();
    }

四、插入数据

可以使用 JdbcClient 的 update 方法进行数据的插入和更新。

通过占位符参数插入数据:

public Integer insertDataWithParam(MyData myData) {
        Integer rowsAffected = jdbcClient.sql("insert into my_data values(?,?) ")
                .param(myData.id())
                .param(myData.name())
                .update();
        return rowsAffected;
    }

通过命名参数插入数据:

public Integer insertDataWithNamedParam(MyData myData) {
        Integer rowsAffected = jdbcClient.sql("insert into my_data values(:id,:name) ")
                .param("id", myData.id())
                .param("name", myData.name())
                .update();
        return rowsAffected;
    }

直接插入整个对象:

public Integer insertDataWithObject(MyData myData) {
        Integer rowsAffected = jdbcClient.sql("insert into my_data values(:id,:name) ")
                .paramSource(myData)
                .update();
        return rowsAffected;
    }

五、总结

通过上述的示例,可以看到基本的数据库操作都可以用 JdbcClient 实现,避免了复杂的ORM框架的使用,切操作要比ORM框架简单灵活的多。fluent API 的风格也更容易编写和阅读。

完整的数据库操作方法的调用演示:

@Slf4j
@SpringBootApplication
public class Application implements CommandLineRunner {

    @Autowired
    private DbService dbService;

    @Override
    public void run(String... args) {
        MyData myData = new MyData(1L, "test");
        log.info("insert rows: {}", dbService.insertDataWithObject(myData));

        MyData myData2 = new MyData(2L, "test");
        dbService.insertDataWithParam(myData2);

        MyData myData3 = new MyData(3L, "author");
        dbService.insertDataWithNamedParam(myData3);

        log.info("findDataById: {}", dbService.findDataById(1L));
        log.info("findDataByName: {}", dbService.findDataByName("test"));
        log.info("findDataWithRowMapper: {}", dbService.findDataWithRowMapper());
        log.info("findDataByParamMap: {}", dbService.findDataByParamMap(Map.of("name""author")));
        log.info("countByName: {}", dbService.countByName("test"));
    }

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

👉 欢迎加入小哈的星球,你将获得: 专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

  • 新项目:《从零手撸:仿小红书(微服务架构)》 正在持续爆肝中,基于 Spring Cloud Alibaba + Spring Boot 3.x + JDK 17..., 点击查看项目介绍
  • 《从零手撸:前后端分离博客项目(全栈开发)》 2期已完结,演示链接:http://116.62.199.48/;

截止目前,累计输出 50w+ 字,讲解图 2200+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,Spring Cloud Alibaba 等等,戳我加入学习,解锁全部项目,已有1800+小伙伴加入


      
         

1. 我的私密学习小圈子~

2. Lombok 同时使用 @Data 和 @Builder 的巨坑,千万别乱用!

3. 你的编程能力从什么时候开始突飞猛进?一个腾讯小哥哥是这样回答的!

4. 好好写简历吧!这简历一看就是包装的!!

最近面试BAT,整理一份面试资料Java面试BATJ通关手册,覆盖了Java核心技术、JVM、Java并发、SSM、微服务、数据库、数据结构等等。

获取方式:点“在看”,关注公众号并回复 Java 领取,更多内容陆续奉上。

PS:因公众号平台更改了推送规则,如果不想错过内容,记得读完点一下在看,加个星标,这样每次新文章推送才会第一时间出现在你的订阅列表里。

“在看”支持小哈呀,谢谢啦

浏览 121
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报