Использовать array_position с API JPA Criteria? - PullRequest
0 голосов
/ 30 октября 2019

Я использую springjpa & postgresql, в моей базе данных есть поле с типом массива bitint, а в Java это значение типа Long.

Я использую Spring jpa CriteriaBuilder & Specification для создания позиции массивафункция:

private Predicate toPredicate(String propName, Query q, Root<T> root, CriteriaBuilder cb) {
    ...
    return cb.isNotNull(cb.function("array_position", Integer.class,
                            xx expression,
                            cb.literal(q.value)));  // q.value is a long type value
}

И когда я выполняю запрос, возникает ошибка:

Hibernate: 
    select
        distinct ruletemp0_.id as id1_119_,
        ruletemp0_.applicant as applican2_119_,
        ruletemp0_.approver as approver3_119_,
        ruletemp0_.devices as devices4_119_,
        ruletemp0_.end_time as end_time5_119_,
        ruletemp0_.execution_id as executio6_119_,
        ruletemp0_.execution_type as executio7_119_,
        ruletemp0_.extra as extra8_119_,
        ruletemp0_.rule_id as rule_id9_119_,
        ruletemp0_.start_time as start_t10_119_,
        ruletemp0_.state as state11_119_,
        ruletemp0_.user_id as user_id12_119_ 
    from
        tbl_ruletemp ruletemp0_ 
    where
        array_position(ruletemp0_.user_id, 1) is not null 
        or array_position(ruletemp0_.user_id, 2) is not null
2019-10-30 10:44:42.230 [WARN ] [main] [org.hibernate.engine.jdbc.spi.SqlExceptionHelper::logExceptions] SQL Error: 0, SQLState: 42883
2019-10-30 10:44:42.230 [ERROR] [main] [org.hibernate.engine.jdbc.spi.SqlExceptionHelper::logExceptions] ERROR: function array_position(bigint[], integer) does not exist
  建议:No function matches the given name and argument types. You might need to add explicit type casts.

Кажется, что jpa не распознает значение типа Long, я пытаюсь использовать:

BigInteger bigInteger = new BigInteger(String.valueOf(q.value));
return cb.isNotNull(cb.function("array_position", Integer.class,
                            toExpression(propName, root),
                            cb.literal(bigInteger)));                    

Все еще ошибка. Если я выполню SQL-запрос в pg напрямую:

select * from tbl_ruletemp t where array_position(t.user_id, cast(1 as BIGINT)) is not null;

будет работать.

А идеи?

1 Ответ

0 голосов
/ 30 октября 2019

Вы можете создать выражение cast с помощью построителя критериев, но это может быть необязательно. Вместо использования числа в качестве литерала, передайте его как параметр.

ParameterExpression<BigInteger> pid = cb.parameter(BigInteger.class, "pid");
return cb.isNotNull(cb.function("array_position", Integer.class,
                            toExpression(propName, root),
                            pid));

Затем просто свяжите параметр, как обычно. А поскольку вы используете массивы, возможно, было бы лучше использовать arrayoverlap вместо цепочки array_position вызовов и or выражений.

...