Spring Data 灵活查询的三种方式

在页面中展示列表数据时,通常需要根据用户输入的不同的查询条件返回不同的查询结果,传统的方式往往采用手动编写原始sql拼接where条件的方式,这种方式并不安全,容易存在sql注入漏洞。

本文介绍用SpringDataJpa实现灵活查询的方式,具体的代码参照 示例项目 https://github.com/qihaiyan/springcamp/tree/master/spring-data-flex-query

一、概述

SpringDataJpa提供了三种灵活查询的方式,分别是:1、通过@Query注解编写查询语句;2、Example查询;3、Specification查询。下面分别介绍这三种方式的使用方法。

二、通过@Query注解编写查询语句

这种方式使用比较简单,在 Repository 方法中编写查询语句。

public interface MyDataRepository extends JpaRepository<MyData, Long>, JpaSpecificationExecutor<MyData> {@Query("select U from MyData U where (?1 is null or U.id=?1) and (?2 is null or U.name=?2)")List<MyData> findByQuery(Long id, String name);
}

为了能够按照不同的查询条件进行查询,需要在查询语句中对查询参数进行判空,将所有的查询参数组合成and查询条件。当某个查询参数为空时,查询路径会被is null覆盖,该查询参数不会对数据进行过滤。

三、Example查询

Example查询是通过一个数据对象按照约定的规则进行查询,只有对象中的非空字段或加入过滤条件,为空的字段不会进行过滤。

public interface MyService {MyData example = new MyData();example.setName("two");log.info("find by example: {}", myDataRepository.findAll(Example.of(example)));
}

在上述代码中,由于我们只对example对象的name字段赋值,因此只会按照name条件进行过滤。

更加详细的使用方式,可以参照[官方文档(https://docs.spring.io/spring-data/jpa/reference/repositories/query-by-example.html)]

四、Specification查询

相比于前两种方式,Specification查询要灵活的多,可以任意组合查询条件,实现我们想要的查询结果。

首先 Repository 要扩展 JpaSpecificationExecutor :

public interface MyDataRepository extends JpaRepository<MyData, Long>, JpaSpecificationExecutor<MyData> {
}

用Specification编写一个查询方法:

private List<MyData> findBySpec(Long id, String name, List<Long> ids) {return myDataRepository.findAll((root, query, builder) -> {List<Predicate> predicates = new ArrayList<>();if (id != null) {predicates.add(builder.equal(root.get("id"), id));}if (name != null) {predicates.add(builder.like(root.get("name"), name));}if (ids != null) {predicates.add(root.get("id").in(ids));}return builder.and(predicates.toArray(new Predicate[0]));}, Sort.by("id").descending());}

在查询方法中,我们分别通过 builder.equal、builder.like、 root.get(“id”).in 实现了 = like in 三个sql子句,除此之外,还有 greaterThan lessThan 等其它很多方法可以使用。

最后一个参数还可以指定分页和排序条件。

使用查询方法进行灵活查询:

log.info("find by spec with id: {}", findBySpec(1L, null, null));
log.info("find by spec with name: {}", findBySpec(null, "%wo%", null));
log.info("find by spec with id list: {}", findBySpec(null, null, List.of(1L, 2L)));

执行程序后,我们可以在日志中看到,不同的查询条件返回了不同的查询结果。

完整的实例代码:

@Slf4j
@SpringBootApplication
public class Application implements CommandLineRunner {@Autowiredprivate MyDataRepository myDataRepository;@Overridepublic void run(String... args) {MyData myData1 = new MyData();myData1.setName("one");myDataRepository.save(myData1);MyData myData2 = new MyData();myData2.setName("two");myDataRepository.save(myData2);log.info("find by id with query: {}", myDataRepository.findByQuery(1L, null));log.info("find by id and name with query: {}", myDataRepository.findByQuery(1L, "one"));MyData example = new MyData();example.setName("two");log.info("find by example: {}", myDataRepository.findAll(Example.of(example)));log.info("find by spec with id: {}", findBySpec(1L, null, null));log.info("find by spec with name: {}", findBySpec(null, "%wo%", null));log.info("find by spec with id list: {}", findBySpec(null, null, List.of(1L, 2L)));}private List<MyData> findBySpec(Long id, String name, List<Long> ids) {return myDataRepository.findAll((root, query, builder) -> {List<Predicate> predicates = new ArrayList<>();if (id != null) {predicates.add(builder.equal(root.get("id"), id));}if (name != null) {predicates.add(builder.like(root.get("name"), name));}if (ids != null) {predicates.add(root.get("id").in(ids));}return builder.and(predicates.toArray(new Predicate[0]));}, Sort.by("id").descending());}public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

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

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

相关文章

C# 委托(Delegate)

C# 委托&#xff08;Delegate&#xff09; C# 委托&#xff08;Delegate&#xff09;声明委托&#xff08;Delegate&#xff09;实例化委托&#xff08;Delegate&#xff09;委托的多播&#xff08;Multicasting of a Delegate&#xff09;委托&#xff08;Delegate&#xff09…

怎么提取视频中的背景音乐?

当我们在刷视频的时候&#xff0c;有时候听到一个背景音乐很好听&#xff0c;但是又不知道歌名&#xff0c;比如英语歌&#xff0c;这个时候我们很难找到这首歌&#xff0c;相信有很多朋友会遇到这样的问题&#xff0c;不知道怎么弄&#xff0c;下面小编给大家推荐一些方法帮助…

MySQL数据表加密字段支持模糊查询的方案

AES_ENCRYPT函数和AES_DECRYPT,需要注意的是&#xff0c;加密后的字段需要用blob做存储&#xff0c;如果用varchar存储会报1366错误。 Mysql本身自带的加密方法&#xff0c;分为2种&#xff1a; 1、不可逆加密算法&#xff1a; PASSWORD&#xff0c;ENCRYPT&#xff0c;MD5&…

名词+of+名词+非谓语动词短语的结构

一、英语中 名词 of 名词 that .,that后面的定语从句修饰的是of前面的名词还是后面的名词?如果是前面或者后面,要反过来怎么搞? eg;There are some present of you that jam sent you yesterday.(这里有一些吉姆昨天送的你的礼物&#xff09;1&#xff09; present of you可…

Pytorch从零开始实战14

Pytorch从零开始实战——DenseNet SENet算法实战 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——DenseNet SENet算法实战环境准备数据集模型选择开始训练可视化总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#x…

亿赛通电子文档安全管理系统 linkfilterservice 未授权漏洞

产品简介 亿赛通电子文档安全管理系统&#xff0c;&#xff08;简称&#xff1a;CDG&#xff09;是一款电子文档安全加密软件&#xff0c;该系统利用驱动层透明加密技术&#xff0c;通过对电子文档的加密保护&#xff0c;防止内部员工泄密和外部人员非法窃取企业核心重要数据资…

TS常用类型

原始类型使用 // 原始类型使用 let age: number 18let myName: string 前端let isLoding: boolean falselet a: null nulllet b: undefined undefinedlet s:symbol Symbol()数组类型使用 // 数组类型的两种写法// 写法一 let numbers: number[] [1, 2, 3] // 数值类型…

Spring企业开发核心框架

文章目录 Spring企业开发核心框架一、框架前言1. 总体技术体系2. 框架概念和理解 二、Spring Framework简介1. Spring 和 SpringFramework2. SpringFramework主要功能模块3. SpringFramework 主要优势 三、Spring IoC 容器概念1. 组件和组件管理概念2. Spring IoC容器和容器实现…

ALS-运动系统解构

角色握持 角色蓝图&#xff1a;将物体绑在手上 动作蓝图&#xff1a; 将握持动画截取一帧&#xff08;explicit time时间写好&#xff09; 角色替换 在原人物模型下面加一个骨骼体&#xff08;先不用添加模型&#xff09;&#xff0c;重命名为bodymesh AI使用流程 新建一…

品牌如何在线上打造“社交货币”?媒介盒子揭秘

品牌的社交货币&#xff0c;是品牌与消费者的共识身份铸造器。竹筒奶茶、Keep奖牌这类的实体产品作为社交货币&#xff0c;每每能够引爆社交平台&#xff0c;那么品牌能否通过线上平台打造“社交货币”呢&#xff1f;接下来就让媒介盒子和大家聊聊。 一、社交货币是什么 社交货…

6.Nacos

1.单机部署 1.1 官网 https://nacos.io/zh-cn/index.html https://github.com/alibaba/Nacos 1.2.版本说明 https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E 1.3.下载地址 https://github.com/alibaba/nacos/releases/tag/2.2.…

小区跑腿服务

社区跑腿服务是指在社区范围内为居民提供各种便利的服务&#xff0c;包括购物代劳、快递代取、家政服务等。 这种服务的出现&#xff0c;满足了居民生活中诸多需求&#xff0c;受到了广泛的欢迎和认可。 首先&#xff0c;社区跑腿服务方便了居民的日常生活。 居民无需亲自前…

Unity 数据存储PlayerPrefs管理类

Unity 数据存储PlayerPrefs管理类 Unity 数据存储PlayerPrefs管理类实现存取实体类对象存储格式为Json格式Singleton.csInventoryEntity.csDataManager.cs用法如下 Unity 数据存储PlayerPrefs管理类 实现存取实体类对象 存储格式为Json格式 源码如下&#xff1a; Singleton…

克魔助手工具下载、注册和登录指南

下载安装克魔助手 摘要 本文介绍了如何下载安装克魔助手工具&#xff0c;以及注册和登录流程。通过简单的步骤&#xff0c;用户可以轻松获取并使用该工具&#xff0c;为后续的手机应用管理操作做好准备。 引言 克魔助手是一款免费的手机管理工具&#xff0c;通过该工具用户…

2023年第十六届山东省职业院校技能大赛高职组“应用软件系统开发”赛项样题

第十六届山东省职业院校技能大赛 高职组“应用软件系统开发”赛项样题 目录 一&#xff0e;竞赛须知 二&#xff0e;竞赛任务 模块一&#xff1a;系统需求分析&#xff08;25分&#xff09; 模块三&#xff1a;系统部署测试&#xff08;20分&#xff09; 需要竞赛源码或资…

Linux常用压缩和解压缩命令

在Linux系统中&#xff0c;有多种压缩和解压缩命令可供使用。以下是一些常用的压缩和解压缩命令的详细解释&#xff1a; 压缩命令 1. gzip 压缩文件&#xff1a; gzip file 这将压缩file并生成一个名为file.gz的压缩文件。 保留原始文件&#xff1a; gzip -c file > fil…

微服务的调用使用

在微服务架构中&#xff0c;不同的微服务之间通常通过网络进行调用和通信。常见的方式包括&#xff1a; 1. **HTTP/HTTPS调用&#xff1a;** 微服务可以通过HTTP或HTTPS协议进行调用。使用HTTP请求方法&#xff08;如GET、POST、PUT、DELETE&#xff09;来执行操作&#xff0c…

【AUTOSAR OS】了解AUTOSAR操作系统基本概念(1)--任务

目录 前言 一、任务Task 什么是“基础任务”和“扩展任务”?以及他们适用于什么场景?

文章解读与完整程序——《考虑“源-荷-储”协同互动的主动配电网优化调度研究》

摘要&#xff1a;伴随智能电网的建设和清洁能源的开发利用,配电网中的负荷类型呈现多元化发展,分布式电源、可控负荷、储能等资源的增加让单向潮流的传统配电网逐渐向双向潮流的主动配电网结构转变。在能源结构转变的同时,清洁能源自身的随机性和波动性给配电网带来了更大的调峰…

2023.12.25 关于 Redis 数据类型 Hash 常用命令、内部编码、应用场景

目录 Hash 数据类型 Hash 操作命令 HSET HGET HEXISTS HDEL HKEYS HVALS HGETALL HMGET HLEN HSETNX HINCRBY HINCRBYFLOAT HSTRLEN Hash 编码方式 理解什么是压缩 Hash 实际应用 Cache 缓存 Hash 数据类型 整体上来说 Redis 是键值对结构&#xff0c;其中 …