dimanche 22 avril 2018

How to get rid of ifs in this case?

I have the building process for Criteria SQL requests but this repeating if() extremely horrible. I want to get rid of theirs. May by Reflection API help me but my struggle is failing. Maybe some who help me with a small example.

@AllArgsConstructor
class PhoneSpecification implements Specification<Phone> {

    private final @NonNull PhoneFilter filter;

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

I thying something like this:

Lists.newArrayList(Phone.class.getDeclaredFields()).forEach(field -> {
    field.setAccessible(true);
    try {
        field.get(filter)
        //...
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }
});

But I confused can I get value and type, and name of field...

Maybe reflection isn't a good way and you know better? Design pattern or something else?

This filter DTO:

@Data
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;
}

Aucun commentaire:

Enregistrer un commentaire