为什么过滤Spring Data JPA规范不起作用?

时间:2018-04-22 05:19:24

标签: java spring-data-jpa

我尝试使用Spring Data JPA过滤器从表中选择数据Specification我认为我的实现是正确的,但它不起作用。请帮助我理解我的错误并修复我的例子。

我在日志中有非常奇怪的SQL查询:

select phone0_.id as id1_0_, phone0_.note as note2_0_, phone0_.number as number3_0_, phone0_.operator_login as operator4_0_, phone0_.operator_pass as operator5_0_, phone0_.operator_name as operator6_0_, phone0_.operator_url as operator7_0_, phone0_.reg_date as reg_date8_0_, phone0_.status as status9_0_ from phone phone0_ where 0=1 limit ?

最后:where 0=1让我大吃一惊。这是从哪里来的?

如果过滤字段不为空,我填写CriteriaBuilder。我希望得到正确构建的Specification对象并将其发送到findAll(Specifications.where(specification), Pageable p)方法。但是有些不正确。

我的回购和规范impl:

public interface PhoneRepository extends CrudRepository<Phone, Integer>, JpaRepository<Phone, Integer>, JpaSpecificationExecutor<Phone> {
    class PhoneSpecification implements Specification<Phone> {

        private final @NonNull PhoneService.PhoneFilter filter;

        public PhoneSpecification(@NonNull PhoneService.PhoneFilter filter) {
            this.filter = filter;
        }

        @Override
        public Predicate toPredicate(Root<Phone> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            Predicate predicate = cb.disjunction();
            if (nonNull(filter.getId())) {
                cb.disjunction().getExpressions().add(cb.equal(root.get("id"), filter.getId()));
            }
            if (nonNull(filter.getNote())) {
                cb.disjunction().getExpressions().add(cb.like(root.get("note"), filter.getNote()));
            }
            if (nonNull(filter.getNumber())) {
                cb.disjunction().getExpressions().add(cb.like(root.get("number"), filter.getNumber()));
            }
            if (nonNull(filter.getStatus())) {
                cb.disjunction().getExpressions().add(cb.like(root.get("status"), filter.getStatus()));
            }
            if (nonNull(filter.getOpName())) {
                cb.disjunction().getExpressions().add(cb.like(root.get("operatorName"), filter.getOpName()));
            }
            if (nonNull(filter.getOpLogin())) {
                cb.disjunction().getExpressions().add(cb.like(root.get("operatorAccLogin"), filter.getOpLogin()));
            }
            if (nonNull(filter.getOpPassword())) {
                cb.disjunction().getExpressions().add(cb.like(root.get("operatorAccPassword"), filter.getOpPassword()));
            }
            if (nonNull(filter.getRegFrom()) && nonNull(filter.getRegTo())) {
                cb.disjunction().getExpressions().add(cb.between(root.get("regDate"), filter.getRegFrom(), filter.getRegTo()));
            }
            return predicate;
        }
    }
}

这是服务级别:

@Service
public class PhoneService {

    @Autowired
    private PhoneRepository phoneRepository;

    public Phone get(int id) {
        Phone phone = phoneRepository.findOne(id);
        return nonNull(phone) ? phone : new Phone();
    }

    public Page<Phone> list(@NonNull PhoneFilter filter) {
        PhoneSpecification specification = new PhoneSpecification(filter);
        return phoneRepository.findAll(Specifications.where(specification), filter.getPageable());
    }

    @Data
    public static class PhoneFilter {

        private Pageable pageable;

        private Integer id;

        private Timestamp regFrom;

        private Timestamp regTo;

        private String number;

        private String opLogin;

        private String opPassword;

        private String opName;

        private String status;

        private String note;

    }
}

和实体

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Table(name = "phone")
@ToString(exclude = {"accounts"})
@EqualsAndHashCode(exclude = {"accounts"})
public class Phone {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @OneToMany(mappedBy = "phone", cascade = CascadeType.DETACH)
    private Collection<SocialAccount> accounts;

    @Column(name = "reg_date")
    private Timestamp regDate;

    @Column(name = "number")
    private String number;

    @Column(name = "operator_url")
    private String operatorUrl;

    @Column(name = "operator_login")
    private String operatorAccLogin;

    @Column(name = "operator_pass")
    private String operatorAccPassword;

    @Column(name = "operator_name")
    private String operatorName;

    @Column(name = "status")
    private String status;

    @Column(name = "note")
    private String note;

}

1 个答案:

答案 0 :(得分:0)

我发现了错误。

方法CriteriaBuilder.disjunction()这是工厂,每当我打电话给他时,我都会得到新的Predicate对象。

此实施CriteriaBuilderImpl

public Predicate disjunction() {
    return new CompoundPredicate(this, BooleanOperator.OR);
}

小心。