将 WHERE IN 子句添加到 JPA 规范

2023-12-23

我正在尝试实现受 IN 子句限制的搜索功能:

我想实现具有过滤器限制的搜索实现:

    @GetMapping("find")
    public Page<MerchantUserDTO> getAllBySpecification(
            @And({
                @Spec(path = "name", spec = LikeIgnoreCase.class),
                @Spec(path = "login", spec = LikeIgnoreCase.class),
                @Spec(path = "email", spec = LikeIgnoreCase.class),
            }) Specification<Users> specification,
            @SortDefault(sort = "login", direction = Sort.Direction.DESC) Pageable pageable
    ) {        
        return merchantUserService.getAllBySpecification(specification, pageable)
                .map(g -> MerchantUserDTO.builder()                   
                        .id(g.getId())
                        .login(g.getLogin())                        
                        .build()
                );
    }

    @Override
    public Page<Users> getAllBySpecification(Specification<Users> specification, Pageable pageable) {
        return dao.findAllByTypeIn(specification, pageable, "MerchantUser");
    }

存储库:

@Repository
public interface MerchantUserRepository extends JpaRepository<Users, Integer>, JpaSpecificationExecutor<Users> {

    Page<Users> findAllByTypeIn(Pageable page, String... types);

    Page<Users> findAllByTypeIn(Specification<Users> specification, Pageable pageable, String... types);
}

使用 IN 子句扩展规范的正确方法是什么?

specification.and(path.in(types))path是一个属性,但是如何正确实现它呢?


一般来说,这可以通过以下方式实现:

  1. 创建规范实施
    public class MerchantUserSpecification implements Specification<Users> {
    
        private final List<String> types;
    
        public MerchantUserSpecification(List<String> types) {
            this.types = types;
        }
    
        @Override
        public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            if (types != null && !types.isEmpty()) {
                return root.get(Users_.type).in(types);
            } else {
                // always-true predicate, means that no filtering would be applied
                return cb.and(); 
            }
        }
  1. 使用方法Page findAll(@Nullable 规范规范, 可分页可分页); https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaSpecificationExecutor.html#findAll-org.springframework.data.jpa.domain.Specification-org.springframework.data.domain.Pageable-继承自JpaSpecificationExecutor接口而不是使用您的自定义findAllByTypeIn(Specification<Users> specification....)
    @Override
    public Page<Users> getAllBySpecification(Specification<Users> specification, Pageable pageable) {
        // combine original specification (passed from outside) and filter-by-types specification
        Specification<Users> finalSpec = Specification.where(specification)
               .and(new MerchantUserSpecification(Arrays.asList("MerchantUser")))
        return dao.findAll(finalSpec, pageable)
    }

P.S.

使用 Java 8+ 以及对于简单的情况(例如您的情况),代码可能会减少更多。而不是实施Specification<T>在单独的类中,您可以创建一个方法

private Specification<Users> typeIn(List<String> types) {
    return (root, query, cb) -> {
        if (types != null && !types.isEmpty()) {
           return root.get(Users_.type).in(types);
        } else {
           // always-true predicate, means that no filtering would be applied
           return cb.and(); 
        }
    }
}

@Override
public Page<Users> getAllBySpecification(Specification<Users> specification, Pageable pageable) {
    // combine original specification (passed from outside) and filter-by-types specification
    Specification<Users> finalSpec = Specification.where(specification)
            .and(typeIn(Arrays.asList("MerchantUser")))
    return dao.findAll(finalSpec, pageable)
}

更新:最短路线

@Override
public Page<Users> getAllBySpecification(Specification<Users> specification, Pageable pageable) {
    // combine original specification (passed from outside) and filter-by-types specification
    Specification<Users> finalSpec = Specification.where(specification)
            .and((root, query, cb) -> root.get(Users_.type).in(Arrays.asList("MerchantUser"))
    return dao.findAll(finalSpec, pageable)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 WHERE IN 子句添加到 JPA 规范 的相关文章

随机推荐