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

本文已收录于专栏
《Java》

背景介绍

  在我们的项目中很多的业务都会设计模糊查询,例如按照姓氏去获取人员的信息,按照手机号的前三位去获取人员的信息等。我们除了正常的手写模糊查询的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()+1];

        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();
            }
        }
        // 添加额外的条件,排除isdelete=1的数据
        predicates[nonNullFields.size()] = criteriaBuilder.notEqual(root.get("isDelete"), 1);

        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封装了一些公共的内容,我们开发的过程中使用起来就比较容易和简单。但是我们在使用的过程中也要明白底层是如何实现,不能只停留在会使用的阶段中。知其然也要知其所以然。


🎯 此文章对你有用的话记得留言+点赞+收藏哦🎯
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
一直以来把数据库的表转换成Entity或DTO都是一件让人头痛的事情,既浪费时间又很繁琐,看着几十上百个表的几百上千个字段,真是一件让人很头痛的事情。 我们也想过很多办法解决这个问题,包括用MyEclipse连接数据库生成JavaBean,但多多少少还是会有一些不尽人意的地方,包括表和表字段的comment总是无法生成,而且还会生成很多无用的注释代码,让代码看起来一点都不干净,配置非常繁琐等等问题。 于是一怒之下,自己动手丰衣足食,就自己用Swing了一个通过数据库的表生成JavaBean的工具,支持MySQL、Oracle、SQLServce,完美支持JPA注解,可以同时生成Entity和DTO,可以自动去除表前缀,并支持去除多个前缀,支持精确指定只生成哪几个表的Bean,也支持模糊查找生成哪几个表的Bean,现在不但成员变量上能生成备注了,而且在Getter和Setter上也能有备注了! 更重要的是所有的配置都能被保存到本地,只要配置过一次,下次使用只要点一下生成JavaBean,下一秒就能拿到你想要的JavaBean了,完全实现秒生成。 这次版本更新如下: 1、修复生成JavaBean后缀错误的问题。 2、新增实体的schema,生成实体时要使用的schema,schema可以自动生成: 如果schema与数据库的用户名相同则dbUsername,如果schema与数据库的库名相同则 dbName。 3、新增设置文件扩展名,现在已经不仅仅只能生成Java Bean了,还可能生成DoNet Bean等等各种各 样的Bean了,只需要配置下用户模板和修改下文件扩展名就可以实现了,简单方便。我在用户 模板中添加了一个DoNet的用户模板,大家可以直接生成DoNet的Bean了。大家如果想要生成其 它编程语言的Bean可以发一个那种编程语言的标准Bean给我,我做成用户模板发布上来。 4、新增继承的父类,生成的JavaBean要继承的父类。 5、新增实现的接口,生成的JavaBean要实现的接口。 6、新增忽略的字段,生成的JavaBean需要忽略的表字段。 7、新增要导入的包,需要导入到JavaBean中的包。 8、新增要排除的包,不需要导入到JavaBean中的包。
一直以来把数据库的表转换成Entity或DTO都是一件让人头痛的事情,既浪费时间又很繁琐,看着几十上百个表的几百上千个字段,真是一件让人很头痛的事情。 我们也想过很多办法解决这个问题,包括用MyEclipse连接数据库生成JavaBean,但多多少少还是会有一些不尽人意的地方,包括表和表字段的comment总是无法生成,而且还会生成很多无用的注释代码,让代码看起来一点都不干净,配置非常繁琐等等问题。 于是一怒之下,自己动手丰衣足食,就自己用Swing了一个通过数据库的表生成JavaBean的工具,支持MySQL、Oracle、SQLServce,完美支持JPA注解,可以同时生成Entity和DTO,可以自动去除表前缀,并支持去除多个前缀,支持精确指定只生成哪几个表的Bean,也支持模糊查找生成哪几个表的Bean,现在不但成员变量上能生成备注了,而且在Getter和Setter上也能有备注了! 更重要的是所有的配置都能被保存到本地,只要配置过一次,下次使用只要点一下生成JavaBean,下一秒就能拿到你想要的JavaBean了,完全实现秒生成。并且集成各种实用工具,使得工作效率瞬间爆棚,生产力瞬间爆表。 第9版更新新增对PostgreSQL的支持。 MySQL使用的数据库Jar包是:mysql-connector-java-5.1.20-bin.jar Oracle使用的数据库Jar包是:classes12.jar SQL Server使用的数据库Jar包是:sqljdbc4.jar PostgreSQL使用的数据库Jar包是:postgresql-9.4.1208.jre7.jar
一直以来把数据库的表转换成Entity或DTO都是一件让人头痛的事情,既浪费时间又很繁琐,看着几十上百个表的几百上千个字段,真是一件让人很头痛的事情。 我们也想过很多办法解决这个问题,包括用MyEclipse连接数据库生成JavaBean,但多多少少还是会有一些不尽人意的地方,包括表和表字段的comment总是无法生成,而且还会生成很多无用的注释代码,让代码看起来一点都不干净,配置非常繁琐等等问题。 于是一怒之下,自己动手丰衣足食,就自己用Swing了一个通过数据库的表生成JavaBean的工具,支持MySQL、Oracle、SQLServce,完美支持JPA注解,可以同时生成Entity和DTO,可以自动去除表前缀,并支持去除多个前缀,支持精确指定只生成哪几个表的Bean,也支持模糊查找生成哪几个表的Bean,现在不但成员变量上能生成备注了,而且在Getter和Setter上也能有备注了! 更重要的是所有的配置都能被保存到本地,只要配置过一次,下次使用只要点一下生成JavaBean,下一秒就能拿到你想要的JavaBean了,完全实现秒生成。 这次版本更新如下: 1、新增查看数据库中所有表的对话框,在精确匹配文本框旁点击更多按钮或双击精确匹配文本框, 即可弹出选择数据库表的对话框,这里将列出数据库中所有的表,并支持模糊查询(不区分大小) 查找需要的表,在复选框中选中需要的表,点确认选择即可。 2、解决Oracle一次转换的表过多时出现超出打开游标的最大数异常,现在测试了一次生成四百多张表 的DTO和Entity成功完成转换,只是表太多速度有点慢。 3、内存占用优化,对占用的内存资源进行清理,极大的减少了程序对系统内存的占用,提高了程序的 运行效率和稳定性。
【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 3、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于springboot+jpa+Erupt的综合签到打卡系统,支持人脸识别源码+项目说明.zip # 快速开始 > 默认账号 - 管理员 admin admin - 默认人脸(手机找个照片然后对着电脑就行) > 项目页面 1. 管理员界面 http://localhost:8080 2. 客户端界面 http://localhost:8080/front.html 3. swagger接口界面 http://localhost:8080/swagger-ui.html#/ > 项目启动 1. 创建数据库face_sign_in并导入/src/face_sign_in.sql 2. 修改/src/main/resources/application-dev.yml里面的配置 3. 对于idea需要配置lombok插件&jdk1.8 | project structure里面level设置成8及以上 4. 使用idea maven 刷新后右上角启动即可 > 功能使用 1. 注册人脸:先创建新用户再前往录入界面录入(不能太模糊,也可以使用明星的照片) 2. 更新人脸:选择已经录入的人脸然后覆盖 3. 录入访客:后端管理界面手动录入或者excel导入 4. 推送手机:前往http://pushplus.hxtrip.com/send配置对应的key,去后端管理配置出覆盖 5. 百度人脸识别:本项目已经接入了我的百度人脸库,如需要自己创建,前往百度控制中心申请覆盖application的配置 > 项目开发 1. 后端基于erupt框架 2. 后端管理页面也基于erupt框架自动生成,开发请前往erupt官网阅读文档 3. 客户端基于uniapp开发,源码打包发布在项目的release里面,将项目导入hbuilder即可直接点击运行,打包后将产物覆盖front文件夹即可 # 一 、项目背景及需求分析 > [docker-compose一键部署](https://github.com/404name/face-check-in-system/releases/tag/1.0.0)(仅需下载docker-compose文件夹运行即可) > 用户在可靠验证下实现简化身份确认 在已有用户数据库基础上<br />**传统校验方式:** 1. 直接选择 ==》 用户 【不安全/不可靠】 1. 用户名 + 密码 查询数据库 ==》 用户 【麻烦/】 **新型校验方式** 3. 第三方工具、qq/微信扫码 ==》 用户 【没手机时麻烦/不稳定】 3. 生物特征人脸/指纹识别 ==》 用户 【方便/可靠】 因此基于各家人脸识别框架,选用百度作为接口,围绕其开发此系统;<br />![动画.gif](https://cdn.nlark.com/yuque/0/2021/gif/21375831/1629635877393-efa7b1b0-5747-48c8-9539-d9586e479687.gif#clientId=u07d94e27-5409-4&from=drop&id=u41487a33&margin=%5Bobject%20Object%5D&name=%E5%8A%A8%E7%94%BB.gif&originHeight=999&originWidth=1909&originalType=binary&ratio=1&size=1955400&status=done&style=none&taskId=ue5f526a0-8b47-4590-a7c4-60f98f434d8)<br />![image.png](https://cdn.nlark.com/yuque/0/2021/png/21375831/1629634914296-d0aeb593-56d8-4770-b208-75f52a4690b1.png#clientId=u07d94e27-5409-4&from=paste&id=uf7d21185&margin=%5Bobject%20Object%5D&name=image.png&originHeight=796&originWidth=1107&originalType=binary&ratio=1&size=671170&status=done&style=none&taskI

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

武梓龙_Wzill

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值