Критерий запроса возвращает [] - PullRequest
0 голосов
/ 12 июня 2019

Я пытаюсь использовать хранилище критериев для поиска записей БД по полям классов, когда некоторые поля классов могут быть нулевыми. Я проверяю строки, целые числа и использую «как» в SQL для проверки битов в двоичном слове.

И мой класс сущности, и моя метамодель находятся в отдельном пакете:

-metapackage
    |
    +-MyEntity1.java
    |
    +-MyEntity1_.java

Это моя метамодель:

    public static volatile SingularAttribute< MyEntity1, String> country;
    public static volatile SingularAttribute< MyEntity1, String> city;
    public static volatile SingularAttribute< MyEntity1, LocalDate> added;
    public static volatile SingularAttribute< MyEntity1, String> address;
    public static volatile SingularAttribute< MyEntity1, UserJPA> userJpa;
    public static volatile SingularAttribute< MyEntity1, String> title;
    public static volatile SingularAttribute< MyEntity1, Integer> size;
    public static volatile SingularAttribute< MyEntity1, String> sizeUnit;
    public static volatile SingularAttribute< MyEntity1, String> flags;// <<<<<<< this is a binary word of 8 bits
    public static volatile SingularAttribute< MyEntity1, Long> id;

Это мой критерий код:

    CriteriaBuilder builder = entityManagerFactory.getCriteriaBuilder();

    CriteriaQuery< MyEntity1> cquerry = builder.createQuery( MyEntity1.class);
    Root< MyEntity1> croot = cquerry.from( MyEntity1.class);

    cquerry.select(croot);
    Predicate pred = builder.isNotNull(croot.<String>get( MyEntity1_.flags));

    if(RestPreconditions.checkString(model.getCity())) {
        pred = builder.and(pred, builder.equal(croot.get( MyEntity1_.city), model.getCity()));
    }
    if(RestPreconditions.checkString(model.getCountry())) {
        pred = builder.and(pred, builder.equal(croot.get( MyEntity1_.country), model.getCountry()));
    }
    if(RestPreconditions.checkString(model.getAddress())) {
        pred = builder.and(pred, builder.equal(croot.get( MyEntity1_.address), model.getAddress()));
    }

    if(model.getMaxSize()!=null) {
        pred = builder.and(pred, builder.lessThanOrEqualTo(croot.get( MyEntity1_.size), model.convertSizeToM2(model.getMaxSize())));
    }
    if(model.getMinSize()!=null) {
        pred = builder.and(pred, builder.greaterThanOrEqualTo(croot.get( MyEntity1_.size), model.convertSizeToM2(model.getMinSize())));
    }
    // .flagsToBword() always returns something
    String bword = model.flagsToBWord();
    if(!bword.matches("0{8}")){
        pred = builder.and(pred, builder.like(croot.<String>get( MyEntity1_.flags), bword.replaceAll("0", "_")));
    }

    return entityManagerFactory.createEntityManager()
            .createQuery(cquerry.where(pred))
            .getResultList();

Проблема в том, что я продолжаю получать пустой список в качестве ответа, хотя я знаю, что в DataBase есть объекты, которые совпадают. Что я делаю не так?

РЕДАКТИРОВАТЬ:

Например, если я хочу найти записи в городе с именем hdhrgdh, это объект, который я отправляю:

{ "Город": "hdhrgdh" }

У меня есть запись базы данных с этим городом в строке.

Кроме того, эта строка кода в начале, когда я создаю свой предикат:

Predicate pred = builder.isNotNull (croot.get (MyEntity1_.flags));

Есть ли просто для начала соединения; флаги никогда не равны нулю

Ответы [ 2 ]

1 голос
/ 12 июня 2019

Вы на правильном пути. Единственная ошибка, которую вы допустили, заключается в том, что вы каждый раз переопределяете значение pred.

Если вы хотите связать операторы where, вы должны переназначить значение pred вместе с предложением + where.

Specification<MyEntity1> spec = Specification.where(
    (root, cb, cq) -> cb.isNotNull(root.get(MyEntity1_.flags)));

if (RestPreconditions.checkString(model.getCity())) 
    spec = spec.and(
        (root, cb, cq) -> cb.equal(root.get(MyEntity1_.city), model.getCity()))

return yourRepository.findAll(spec);
0 голосов
/ 12 июня 2019

Я наконец понял это.

Когда я звоню:

String bword = model.flagsToBWord();

Я бы объединил массив флагов в строковое / двоичное слово, используя java.util.Arrays

И это будет производить строку вроде:

"[0,0,1,0,0,1,0,1]"

Вместо обычного двоичного слова, которое мне было нужно:

"00100101"

Конечно, это не сработало; он всегда искал запись с недопустимым значением LIKE.

Теперь все работает правильно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...