【问题标题】:Spring predicate multiple operatorsSpring谓词多个运算符
【发布时间】:2018-08-07 12:07:15
【问题描述】:

我正在尝试使用多种过滤方法制作可排序/可分页/可过滤的存储库。这就是我的相关代码现在的样子:

@Entity
@Table(name = "user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = "name", length = 50, nullable = false)
private String name;

存储库:

@Repository
public interface UserRepository extends JpaRepository<User, Long> , 
QuerydslPredicateExecutor<User> {
}

还有控制器:

@RequestMapping(path="/test")
public @ResponseBody ResponseEntity<Object> foo
( @QuerydslPredicate(root = User.class) Predicate predicate, Pageable pageable) {
    return userRepository.findAll(predicate,pageable);
}

它工作得很好,像这样: /users/?page=0&limit=1&sort=name,ASC&name=testuser 但我不能使用任何其他过滤方法,除了“name=testuser”之类的等号 我四处寻找,一直在寻找this 之类的指南,但我必须为每个实体编写一个 PathBuilder,而且控制器看起来也更丑陋。

有没有办法解决这个问题并像现在一样保持一切简化?我需要 eq,neq,gte,lte,like 等基本运算符...

【问题讨论】:

  • 您不需要为每个实体编写 PathBuilder。生成 querydsl 对象时,可以在 QuerydslBinderCustomizer 中访问该对象。
  • 您能给出一些解释或举个例子吗?

标签: java spring operators predicate


【解决方案1】:

一般我使用CriteriaBuilder API。它为我提供了一个小解决方案,您只需将存储库订阅到您的自定义规范即可。

public class CustomerSpecification implements Specification<CustomerDetail> {

    private C2Criteria criteria;

    public static CustomerSpecification of(C2Criteria criteria) {
        return new CustomerSpecification(criteria);
    }

    private CustomerSpecification(C2Criteria criteria) {
        this.criteria = criteria;
    }

    @Override
    public Predicate toPredicate
        (Root<CustomerDetail> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
    return getPredicate(root, builder, criteria);
   }
}

public <T> Predicate getPredicate(Root<T> root, CriteriaBuilder builder, C2Criteria criteria) {

    if (criteria.getOperation().equalsIgnoreCase(">")) {
        return builder.greaterThanOrEqualTo(
                root.get(criteria.getKey()), criteria.getValue().toString());
    } else if (criteria.getOperation().equalsIgnoreCase("<")) {
        return builder.lessThanOrEqualTo(
                root.get(criteria.getKey()), criteria.getValue().toString());
    } else if (criteria.getOperation().equalsIgnoreCase(":")) {
        if (root.get(criteria.getKey()).getJavaType().equals(String.class)) {
            return builder.like(
                    root.get(criteria.getKey()), "%" + criteria.getValue() + "%");
        } else {
            return builder.equal(root.get(criteria.getKey()), criteria.getValue());
        }
    }

我的标准类是:

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class C2Criteria {
    private String key;
    private String operation = ":";
    private Object value;
}

而我的JpaRepository 看起来像:

public interface CustomerDetailRepository extends JpaRepository<CustomerDetail, Long>, JpaSpecificationExecutor<CustomerDetail> {
}

在您的控制器中,您可以通过从 queryString 获取对象来使用它。

@GetMapping(value = "renew")
public ResponseEntity renew(@NonNull PageDto page, @NonNull C2Criteria criteria) {
    Page<InsuranceRenew> renews = this.insuranceService.getRenew(page, criteria);
    return ResponseEntity.ok(renews);
}

保险服务方法如下:

@Override
public Page<InsuranceRenew> getRenew(@NonNull PageDto page, @NonNull C2Criteria criteria) {
    Pageable pageable = PageRequest.of(page.getPage(), page.getSize(), new Sort(page.getSort(), page.getOrderBy()));
    InsuranceRenewSpecification specification = InsuranceRenewSpecification.of(criteria);
    return this.renewRepository.findAll(specification, pageable);
}

你可以看到我使用了一个PageDto类,它只是一个POJO,带有一些用于分页目的的字段,它被定义为:

@Data
public class PageDto {
    private int page;
    private int size = 10;
    private Sort.Direction sort = Sort.Direction.DESC;
    private String orderBy = "id";
}

如您所见,我曾经使用 id 作为默认 order by 以防止不需要的异常,并将 DESC 作为默认值。

希望对您有所帮助。

【讨论】:

  • 这里可以找到明确的解释:baeldung.com/…
  • 我需要为每个实体编写规范吗?我如何在 Controller 和 url 中使用它?对不起,我缺乏理解
  • 是的,您应该为要过滤的每个实体编写一个规范类。因此,我为您提供了具有泛型类型的 getPredicate 方法。
  • 我现在正在编辑我的回复,以便在 restcontroller 端添加您如何使用它。
猜你喜欢
  • 2022-11-30
  • 1970-01-01
  • 2011-01-13
  • 1970-01-01
  • 2015-05-22
  • 2011-03-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多