Spring Boot 3.2 新特性之 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 {@Autowiredprivate 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 {@Autowiredprivate DbService dbService;@Overridepublic 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);}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/172370.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Redis报错:JedisConnectionException: Could not get a resource from the pool

1、问题描述&#xff1a; redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool 2、简要分析&#xff1a; redis.clients.util.Pool.getResource会从JedisPool实例池中返回一个可用的redis连接。分析源码可知JedisPool 继承了 r…

mysql常见的十种错误简要说明

错误1064 - SQL语法错误&#xff1a; 当SQL查询存在语法错误时会发生这种错误。请仔细检查查询以查找并纠正错误。 错误1045 - 拒绝访问&#xff1a; 当用户尝试连接到数据库但没有正确的权限或密码不正确时&#xff0c;会发生此错误。 错误2002 - 通过套接字无法连接到本地M…

BigDecimal的使用全面总结

BigDecimal BigDecimal可以表示任意大小&#xff0c;任意精度的有符号十进制数。所以不用怕精度问题&#xff0c;也不用怕大小问题&#xff0c;放心使用就行了。就是要注意的是&#xff0c;使用的时候有一些注意点。还有就是要注意避免创建的时候存在精度问题&#xff0c;尤其…

Spring全面详解(学习总结)

Spring FrameWork一、 前言二、IOC(控制反转)2.1 对于IOC的理解2.2如何使用IOC2.3配置文件的解读2.4IOC容器创建bean的两种方式2.5从IOC容器中取bean2.6bean的属性如果包含特殊字符 三、DI(依赖注入)四、Spring中的bean五、Spring中的继承六、Spring的依赖七、Spring读取外部资…

【咕咕送书 | 第六期】深入浅出阐述嵌入式虚拟机原理,实现“小而能”嵌入式虚拟机!

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏:《粉丝福利》 《linux深造日志》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 ⛳️ 写在前面参与规则引言一、为什么嵌入式系统需要虚拟化技术&#xff1f;1.1 专家推荐 二、本书适合谁&#x…

Git介绍和基础命令解析

Git基本操作指令 工作区和暂存区 Git管理的文件分为&#xff1a;工作区(本地的文件夹)&#xff0c;版本库(.git文件夹)&#xff0c;版本库又分为暂存区stage和暂存区分支master(仓库) 工作区>>>>暂存区>>>>仓库 git add把文件从工作区>>>…

WiFi的CSMA/CA竞争窗口流程简述

1、若站点最初有数据要发送&#xff08;不是发送不成功再进行重传的那种&#xff09;&#xff0c;且检测到信道空闲&#xff0c;在等待DIFS后&#xff0c;就发送整个数据帧。 2、否则&#xff0c;站点执行退避算法。一旦检测到信道忙&#xff0c;就冻结退避计时器。只要信道空…

Less 安装教程

文章目录 前言LESS的系统要求安装LESS例子输出Less编译css工具后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;Sass和Less &#x1f431;‍&#x1f453;博主在前端领域还有很多知识和技术需要掌握&#xff0c;正在不断努力填补技术短板…

error LNK2038: 检测到“RuntimeLibrary”的不匹配项 解决方法

问题&#xff1a; 我们在使用Visual Studio编程的时候偶尔会遇到以下三种报错&#xff1a; error LNK2038: 检测到“RuntimeLibrary”的不匹配项: 值“MD_DynamicRelease”不匹配值“MDd_DynamicDebug” &#xff08;引用的是release模式&#xff0c;但设置成debug模式了…

开源博客项目Blog .NET Core源码学习(7:FluentValidation使用浅析)

开源博客项目Blog .NET使用FluentValidation模块定义数据验证项&#xff0c;具体而言&#xff0c;是在App.Application项目中定义验证类&#xff0c;设置验证规则&#xff0c;同时在App.Framwork项目中基于FluentValidation.AspNetCore包设置ASP.NET验证管道自动验证。   App…

操作系统——进程管理

文章目录 进程和线程进程的概念进程和程序的区别PCB(进程控制块)程序是如何运行的进程的特征进程的状态和状态转换五态模型 进程控制进程状态装换为啥需要保证原子性如何实现原语的原子性&#xff1f; 进程控制相关原语进程创建进程终止进程的阻塞和唤醒进程的唤醒进程的切换 进…

1603. 整数集合划分(2016年408数据结构算法题)

一、题目 1603. 整数集合划分https://www.acwing.com/problem/content/description/1605/ 二、算法的基本设计思想 由题意知&#xff0c;将最小的 个元素放在 中&#xff0c;其余的元素放在 中&#xff0c;分组结果即可满足题目要求。仿照快速排序的思想&#xff0c;基于枢…

Vue 2.0源码分析-Virtual DOM

Virtual DOM 这个概念相信大部分人都不会陌生&#xff0c;它产生的前提是浏览器中的 DOM 是很“昂贵"的&#xff0c;为了更直观的感受&#xff0c;我们可以简单的把一个简单的 div 元素的属性都打印出来&#xff0c;如图所示&#xff1a; 可以看到&#xff0c;真正的 DOM …

地铁在线售票vue票务系统uniAPP+vue 微信小程序

功能介绍 管理员 &#xff08;1&#xff09;管理员登录功能 &#xff08;2&#xff09;查看和修改线路信息 &#xff08;3&#xff09;减少线路 &#xff08;4&#xff09;修改价格&#xff08;5站3元 5-10 5元 10-15站6元 往上8元&#xff09; &#xff08;5&#xff09;删除用…

吾爱破解置顶的“太极”,太好用了吧!

日常工作和娱乐&#xff0c;都需要用到不同类型的软件&#xff0c;哪怕软件体积不大&#xff0c;也必须安装&#xff0c;否则到用时找不到就非常麻烦了。 其实&#xff0c;很多软件不一定一样不剩地全部安装一遍&#xff0c;一方面原因是用的不多&#xff0c;另一方面多少有点…

VS快捷键使用技巧(超全)

VS快捷键使用技巧&#xff08;超全&#xff09; 蒸汽小毛 蒸汽小毛 1.注释&#xff1a;CTRLKC 2.取消注释&#xff1a;CTRLKU 3.设置断点调试&#xff1a;F9&#xff0c;断点行不执行 4.回到上一个光标位置&#xff1a;CTRL 5.前进到下一个光标位置&#xff1a;CTRLShift …

Android设计模式--外观模式

弈之为术&#xff0c;在人自悟 一&#xff0c;定义 外观模式要求一个子系统的外部与其内部的通信必须通过一个统一的对象进行。提供一个高层次的接口&#xff0c;使得子系统更易于使用。 外观模式在开发中的使用频率是非常高的&#xff0c;尤其是在第三方的SDK里面&#xff0…

Django之admin页面样式定制(Simpleui)

好久不见&#xff0c;各位it朋友们&#xff01; 本篇文章我将向各位介绍Django框架中admin后台页面样式定制的一个插件库&#xff0c;名为Simpleui。 一&#xff09;简介 SimpleUI是一款简单易用的用户界面&#xff08;UI&#xff09;库&#xff0c;旨在帮助开发人员快速构建…

CSRF 漏洞的理解

CSRF 漏洞的理解 1. 漏洞描述 CSRF 漏洞是一种web 应用安全漏洞&#xff0c;攻击者可以利用该漏洞伪造的身份执行未授权的操作。 2. 漏洞原理 CSRF 漏洞的原理是 攻击者通过诱使受害者访问恶意网站或点击恶意链接时&#xff0c;利用用户已经登陆的身份来发送一写恶意请求给目标…

清华提出 SoRA,参数量只有 LoRA 的 70%,表现更好!

现在有很多关于大型语言模型&#xff08;LLM&#xff09;的研究&#xff0c;都围绕着如何高效微调展开。微调是利用模型在大规模通用数据上学到的知识&#xff0c;通过有针对性的小规模下游任务数据&#xff0c;使模型更好地适应具体任务的训练方法。 在先前的工作中&#xff…