JPA在不写sql的情况下实现模糊查询

news2024/11/26 17:42:56
本文已收录于专栏
《Java》

目录

  • 背景介绍
  • 概念说明
    • 单字段模糊匹配:
    • 多字段模糊匹配:
  • 实现过程
    • 代码实现
      • 1.写一个实体类去实现Specification接口,重写toPredicate方法
      • 2.定义一个接口去继承JpaRepository接口,并指定返回的类型和参数类型
      • 3.在业务类中调用声明的接口
      • 4.在Controller中直接调用业务类中的方法即可
    • 执行结果
  • 其他方式
    • 1.使用JPQL进行模糊查询:
    • 2.使用Spring Data JPA的Query By Example进行模糊查询:
    • 3.使用Spring Data JPA的@Query注解进行模糊查询:
  • 总结提升

背景介绍

  在我们的项目中很多的业务都会设计模糊查询,例如按照姓氏去获取人员的信息,按照手机号的前三位去获取人员的信息等。我们除了正常的手写模糊查询的sql语句去获取信息之外,还可以使用JPA自带的API来实现任意字段的模糊查询。JPA已经给我们封装好了。当我们对模糊查询非常熟悉了之后直接拿来时候即可。

概念说明

单字段模糊匹配:

说明:在一个字段中无论关键字出现在什么位置上,只要有关键词即可。
场景:获取手机号开头为187的学生
应用:SELECT*FROM table_name WHERE BINARY column_name LIKE'%keyword%';

多字段模糊匹配:

说明:在多个字段中无论关键字出现在什么位置上,只要每个字段有每个字段指定的关键词即可。
场景:获取手机号开头为187并且姓氏为武的学生
应用:SELECT*FROM table_name WHERE BINARY column1_name LIKE'%keyword1%'AND column2_name LIKE'%keyword2%';

  注:BINARY函数是开启大小写敏感的函数,底层逻辑是通过Ascii码的方式比较的。因为数据库默认是对大小写不敏感的,也就是我们在查询名称为wzl数据的时候,也会把名称为Wzl的数据也查询出来。

实现过程

代码实现

1.写一个实体类去实现Specification接口,重写toPredicate方法

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.tfjybj.dao.UserDao;
import com.tfjybj.utils.SnowflakeIdWorker;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import javax.persistence.*;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @BelongsProject: incentive
 * @BelongsPackage: com.tfjybj.service
 * @Author: Wuzilong
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-08-28 14:48
 * @Version: 1.0
 */
@Table
@Entity
@Service
@Data
public class User implements Specification<User> {

    @Id
    @JsonSerialize(using = com.fasterxml.jackson.databind.ser.std.ToStringSerializer.class)
    private Long id;

    private String account;

    private  String password;

    private String phone;

    private Date createTime;

    private Date updateTime;

    private Integer isDelete;

    @Resource
    @Transient
    private UserDao userDao;

    @Override
    public Predicate toPredicate(Root<User> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
        List<String> nonNullFields = new ArrayList<>();
        Field[] declaredFields = this.getClass().getDeclaredFields();
        for (Field field : declaredFields) {
            field.setAccessible(true);
            try {
                Object value = field.get(this);
                if (value != null) {
                    nonNullFields.add(field.getName());
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }

        Predicate[] predicates = new Predicate[nonNullFields.size()];

        for (int i = 0; i < nonNullFields.size(); i++) {
            try {
                predicates[i] = criteriaBuilder.like(root.get(nonNullFields.get(i)), "%" + this.getClass().getDeclaredField(nonNullFields.get(i)).get(this) + "%");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        return criteriaBuilder.and(predicates);
    }
}

本文中实现的是and方式的模糊查询,也可是使用or的方式进行模糊查询,也就是多个字段中都包含一个关键字。

2.定义一个接口去继承JpaRepository接口,并指定返回的类型和参数类型

@Entity
import com.tfjybj.service.User;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import java.util.List;

/**
 * @BelongsProject: incentive
 * @BelongsPackage: com.tfjybj.dao
 * @Author: Wuzilong
 * @Description: 描述什么人干什么事儿
 * @CreateTime: 2023-08-28 14:48
 * @Version: 1.0
 */
@Repository
public interface UserDao extends JpaRepository<User, Long> {

    List<User> findAll(Specification<User> userInfo);
}

3.在业务类中调用声明的接口

@Entity
    public List<User> selectToFuzzy(User userInfo){
        List<User> userInfoList = userDao.findAll(userInfo);
        return userInfoList;
    }

4.在Controller中直接调用业务类中的方法即可

    @RequestMapping(value="selectToFuzzy",method= RequestMethod.POST)
    //模糊查询用户的信息
    public List<User> selectToFuzzy(@RequestBody User userInfo){
        List<User> users = user.selectToFuzzy(userInfo);
        return users;
    }

执行结果

在这里插入图片描述

在这里插入图片描述

  可以看到我们的入参都是对应字段值的一部分内容,phone字段传入的是187它会把phone字段中包含187的所有数据都返回回来。同样两个字段一起模糊查询也是一样。

其他方式

1.使用JPQL进行模糊查询:

使用LIKE关键字结合通配符(%)进行模糊匹配。
例如:SELECT e FROM Employee e WHERE e.name LIKE '%John%'

2.使用Spring Data JPA的Query By Example进行模糊查询:

创建一个实体对象作为查询条件,设置需要模糊匹配的属性值。
例如:ExampleMatcher matcher = ExampleMatcher.matching().withMatcher("name", match -> match.contains()); Example<Employee> example = Example.of(employee, matcher);

3.使用Spring Data JPA的@Query注解进行模糊查询:

在Repository接口中使用@Query注解定义自定义的查询方法。
在查询方法中使用%通配符进行模糊匹配。
例如:@Query("SELECT e FROM Employee e WHERE e.name LIKE %?1%") List<Employee> findByName(String name);

总结提升

  根据自己的业务需求去选择使用哪一种模糊查询的方式。底层原理都是一样的。JPA封装了一些公共的内容,我们开发的过程中使用起来就比较容易和简单。但是我们在使用的过程中也要明白底层是如何实现,不能只停留在会使用的阶段中。知其然也要知其所以然。


🎯 此文章对你有用的话记得留言+点赞+收藏哦🎯

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

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

相关文章

YOLOv5训练后利用权重对特征图可视化

我们可以可视化某层的特征图添加到论文中&#xff0c;属于锦上添花了&#xff01; 小小的技巧&#xff0c;有需要的同学可以自取代码尝试一下。 python detect.py --weights best.pt --imgsz 640 --source ./data/image/ --visualize运行过程中&#xff1a; 运行后即可生成特…

大数据学习:haproxy实现impala的负载均衡

HAProxy实现Impala的负载均衡 1.HAProxy安装及启停 1.1 在集群中选择一个节点&#xff0c;使用yum方式安装HAProxy服务 [rootdata01-dev ~]# yum -y install haproxy1.2 启动与停止HAProxy服务&#xff0c;并将服务添加到自启动列表 [rootdata01-dev ~]# service haproxy s…

Redis持久化——RDF与AOF两种方式怎么做?有什么区别?

目录 1. 什么是RDB 2. save 和 bgsave 命令主动保存数据 2.1 save 2.2 bgsave 3. Redis 内部自动RDB机制 4. RDB 底层是如何实现 bgsave 的&#xff1f; 5. RDB 的缺点 6. 什么是AOF&#xff1f; 7. AOF文件的缺点&#xff1f; 8. AOF 重写文件配置 9. RDB 与 AOF …

Unexpected mutation of “xxxx“ prop

原因 是因为子级修改了父级的数据&#xff0c;所以eslint执行的时候报了这个错 修复方式 1 如果是弹窗等组件&#xff0c;可以根据功能进行修改&#xff0c;比如我这块用的 element ui 的 dialog&#xff0c;便可以改成这样 使用 model-value 代替 修复方式 2 新建子组件…

CTFhub-文件上传-MIME绕过

用哥斯拉生成 php 木马文件 1.php 抓包---> 修改 conten-type 类型 为 imge/jpeg 用蚁剑连接 ctfhub{8e6af8109ca15932bad4747a}

云计算的三个主要服务模型:IaaS、PaaS 和 SaaS

文章目录 介绍基础设施即服务&#xff08;Infrastructure as a Service&#xff0c;IaaS&#xff09;平台即服务&#xff08;Platform as a Service&#xff0c;PaaS&#xff09;软件即服务&#xff08;Software as a Service&#xff0c;SaaS&#xff09; 区别基础设施即服务&…

VS2022 Community 安装步骤

VS2022 Community 安装步骤&#xff08;C语言学习&#xff09; 1. 下载地址2. 安装步骤 1. 下载地址 链接: VS2022 Community下载地址 2. 安装步骤 双击图标进行安装。 点击【继续】后等待安装。 选择需要的安装包并修改安装位置&#xff0c;然后点击【安装】。 点击安装…

vue 小黑记事本

vue 小黑记事本 下面这个界面用html和css 如何搞出来&#xff1f;

市面上的ipad国产触控笔怎么样?适合开学买电容笔推荐

自从ipad之类的平板电脑上出现了电容笔&#xff0c;电容笔就成功的取代了我们的手指&#xff0c;大大加快了我们的写作速度。不过&#xff0c;苹果推出的这款电容笔&#xff0c;由于其特殊的压感和芯片技术&#xff0c;价格一直很贵&#xff0c;很多人都很难买得起&#xff0c;…

Error encountered when performing Introspect database postgres schema

我在使用postgresql数据库的时候遇到了这两个异常: 并且查看不到数据库里的表信息 Error encountered when performing Introspect database postgres schema public (details): 错误: 字段 t.relhasoids 不存在 Error encountered when performing Introspect database pos…

Python钢筋混凝土结构计算.pdf-混凝土强度设计值

计算原理&#xff1a; 需要注意的是&#xff0c;根据不同的规范和设计要求&#xff0c;上述公式可能会有所差异。因此&#xff0c;在进行混凝土强度设计值的计算时&#xff0c;请参考相应的规范和设计手册&#xff0c;以确保计算结果的准确性和合规性。 代码实现&#xff1a; …

2023年天府杯——C 题:码头停靠问题

问题背景&#xff1a; 某个港口有多个不同类型的码头&#xff0c;可以停靠不同种类的船只。每 艘船只需要一定的时间来完成装卸货物等任务&#xff0c;并且每个码头有容量 限制和停靠时间限制。港口需要在保证收益的情况下&#xff0c;尽可能地提高 运营效率和降低成本。同…

快速上手: Linux环境配置, 基本指令与项目部署要点

文章目录 1. Linux前置知识1.1. 什么是Linux1.2. Linux环境的搭建 2. Linux常用命令lscd pwdtouch cat more echo mkdirvi/vimrm cp mvgrep ps netstat 管道符yum相关Linux权限 3. 使用Linux部署Servlet项目3.1. 安装JDK3.2. 安装Tomcat3.3. 通过yum安装MariaDB3.4. 部署Servle…

vue3和vue2的主要区别

Vue 3 和 Vue 2 之间有几个主要的区别&#xff1a; 性能优化&#xff1a;Vue 3 在性能方面进行了一些改进&#xff0c;包括更快的渲染速度和更小的包大小。Vue 3 使用了新的响应式系统&#xff0c;可以更好地追踪依赖关系&#xff0c;从而提高了渲染性能。 Composition API&am…

深圳科普宣传片的重要性

科普宣传片是指科学普及宣传片&#xff0c;旨在向公众传播科学知识、提高科学素养、促进科学文化的传播和科学教育。接下来由深圳科普宣传片制作公司老友记小编从以下几个方面浅析科普宣传片的重要性: 1.普及科学知识&#xff1a;科普宣传片可以向大众传达科学知识&#xff0c;…

PYTHON用户流失数据挖掘:建立逻辑回归、XGBOOST、随机森林、决策树、支持向量机、朴素贝叶斯和KMEANS聚类用户画像...

原文链接&#xff1a;http://tecdat.cn/?p24346 在今天产品高度同质化的品牌营销阶段&#xff0c;企业与企业之间的竞争集中地体现在对客户的争夺上&#xff08;点击文末“阅读原文”获取完整代码数据&#xff09;。 “用户就是上帝”促使众多的企业不惜代价去争夺尽可能多的客…

【紫光同创国产FPGA教程】——【PGL22G第六章】密码锁实验例程

本原创教程由深圳市小眼睛科技有限公司创作&#xff0c;版权归本公司所有&#xff0c;如需转载&#xff0c;需授权并注明出处 适用于板卡型号&#xff1a; 紫光同创PGL22G开发平台&#xff08;盘古22K&#xff09; 一&#xff1a;盘古22K开发板&#xff08;紫光同创PGL22G开发…

「2024」预备研究生mem-相同元素问题仅选取隔板法相邻与不相邻问题

一、相同元素问题&仅选取&隔板法&相邻与不相邻问题 不理解可以不考虑这种方法&#xff1a; 隔板法&#xff1a; 使用分堆分配&#xff0c;此时比较麻烦&#xff1a;

基于Java+SpringBoot+Vue前后端分离智能学习平台系统设计和实现

博主介绍&#xff1a;✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、Java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专…

part-01 C++知识总结(程序的内存分区、多态的实现)

总结来自&#xff1a;拓跋阿秀大佬的面试知识网站&#xff0c;侵权删 一.程序的内存分区/程序模型 内存分区分别是堆、栈&#xff0c;自由存储区&#xff0c;全局/静态存储区、常量存储区和代码存储区。 栈&#xff1a;在执行函数时&#xff0c;函数内局部变量的存储单元都可以…