• 【实战】如何使用Spring Boot Jpa中的findAll进行specification动态查询


    项目场景:使用Spring Data Jpa中的Specification动态查询

    jdk: 1.8
    Spring Boot Version: 2.6.1
    接口文档: Swagger2

    本文将详解如何使用JpaSpecificationExecutor中的复杂查询分页接口实现多参数动态查询。

    一:实体层

    假如有一个实体类为用户:User,先建立实体类:

    @Data
    @Entity
    @Table(name = "user")
    public class User {
    
    	private Long id;
    	private String name;
    	private Integer age;
    	private String phoneNumber;
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    二:Jpa接口层

    引入需要的Jpa Repository接口:

    @Repository
    public interface UserRepository extends JpaRepository<User, Long>, JpaSpecificationExecutor<User> {
    
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三:service逻辑层

    public interface UserService {
    
    	// 分页-列表-动态查询-接口 
    	List<User> listPage(Map<String, Object> params, idList);
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    @Service("UserService")
    public class UserServiceImpl implements UserService {
    
    	@Resource
    	private UserService service;
    	@Resource
    	private UserRepository repository;
    
    	@Override
    	public List<User> listPage(Map<String, Object> params, idList) {
    		// 直接调用repository中继承的接口,这里的JpaPageUtil是自己封装的分页工具,不作详解
    		// 使用自定义的whereUser静态方法,详解在下方
    		Page<User> list = repository.findAll(whereUser(params, idList), JpaPageUtil.getPageRequest(params));
            return list;
            
            }
    
    	// 自定义动态查询参数Specification, 自定义一个 whereUser 静态方法
    	private static Specification<user> whereUser(params, idList) {
    	
    		return (Root<SystemField> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
    		// new一个查询条件,用来存放自定义的查询条件
    		List<Predicate> predicates = new ArrayList<>();
    		// 获取params中的 age,name,phoneNumber
    		Integer age = MapUtil.getInteger(params, "age");
    		String name = MapUtil.getString(params, "name");
    		String phoneNumber = MapUtil.getString(params, "phoneNumber");
    	
    		// 假如前端传了idList,则查询出 id in idList 的所有用户
    		if (CollUtil.isNotEmpty(idList)) {
                    predicates.add(root.get("id").in(idList));
            }
            // 假如前端传了age,找出age匹配的所有用户
            if (age!= null) {
                    predicates.add(cb.equal(root.get("age"), age));
            }
            // 假如前端传了name,写一个模糊查询找出匹配的所有用户
            if (StringUtils.isNotBlank(name)) {
                    predicates.add(cb.like(root.get("name"), "%" + name + "%"));
            }
            // phoneNumer查询
            if (phoneNumber!= null) {
                    predicates.add(cb.equal(root.get("phoneNumber"), phoneNumber));
            }
            
            // 最后,返回封装的所有查询条件
    		return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
            
            };
    }
        
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    四:controller控制层

    @RestController
    @RequestMapping("/user")
    public class userController (
    
    	@Resource
    	private UserService service;
    
    	@GetMapping("/list")
    	    @ApiImplicitParams({
                @ApiImplicitParam(name = "age", value = "年龄",required = false),
                @ApiImplicitParam(name = "name", value = "姓名"required = false),
                @ApiImplicitParam(name = "phoneNumber", value = "电话",required = false),
                @ApiImplicitParam(name = "currPage", value = "页码",,required = false),
                @ApiImplicitParam(name = "pageSize", value = "每页数据量",required = false)
        })
    	public List<User> listPage(@RequestParam Map<String, Object> params) {
    	
    		return service.listPage(params);
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    至此,在 user/list 这一个接口中,就实现了多条件的复杂查询,相较于传统方式非常的简便,减少了代码量和多余接口。但是,这种方式适用于单表的多条件动态查询,如果涉及到了多表的复杂查询,还是推荐使用Mybatis方式。

  • 相关阅读:
    C语言再学习-001-hello c
    23-Spring事务源码分析
    SQL面试题之按照指定顺序进行多行转一列
    桌面运维。
    修改变量的值(变量与常量)
    元宇宙的火爆让人们忽略了区块链的存在,这无益于元宇宙的发展
    【极术读书】赠卡活动第二期,免费领极客时间月卡系统学习技术管理
    基于miniprogram-ci的微信小程序的CI以及接入钉钉通知
    java基础-集合
    java api System类
  • 原文地址:https://blog.csdn.net/weixin_46005530/article/details/132626158