当前位置: 代码网 > it编程>数据库>MsSqlserver > JPA在不写sql的情况下如何实现模糊查询

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

2024年11月21日 MsSqlserver 我要评论
背景介绍在我们的项目中很多的业务都会设计模糊查询,例如按照姓氏去获取人员的信息,按照手机号的前三位去获取人员的信息等。我们除了正常的手写模糊查询的sql语句去获取信息之外,还可以使用jpa自带的api

背景介绍

在我们的项目中很多的业务都会设计模糊查询,例如按照姓氏去获取人员的信息,按照手机号的前三位去获取人员的信息等。

我们除了正常的手写模糊查询的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封装了一些公共的内容,我们开发的过程中使用起来就比较容易和简单。

但是我们在使用的过程中也要明白底层是如何实现,不能只停留在会使用的阶段中。知其然也要知其所以然。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com