Я пытаюсь использовать подготовленный запрос с запросом «где xxx in ()», используя параметр Set of Long as:
public static Multi<Item> findAll(PgPool client, Set<Long> ids) {
Tuple parameter = Tuple.of(ids.toArray(new Long[]{}));
// Tuple parameter = Tuple.wrap(new ArrayList(ids));
return client.preparedQuery("SELECT id, name, properties FROM items where id in ($1)").execute(parameter)
.onItem().transformToMulti(set -> Multi.createFrom().iterable(set))
.onItem().transform(Item::from);
}
Но хотя предполагается, что SQL-запрос «in» обрабатывает несколько значений, он работает при передаче массива, выдавая следующее:
io.vertx.core.impl.NoStackTraceThrowable: Parameter at position[0] with class = [[Ljava.lang.Long;] and value = [[Ljava.lang.Long;@1a074753] can not be coerced to the expected class = [java.lang.Number] for encoding.
Передача одного значения работает, но это не цель метода:
Tuple parameter = Tuple.of(1206756351360216067L);
Каким будет правильный способ обработки набора идентификаторов, чтобы вернуть несколько строк?
Редактировать
В итоге я сделал это:
Tuple parameter = Tuple.of(ids.toArray(new Long[]{}));
String query = "with values as (\n" +
"select unnest(($1)::bigint[]) as id\n" +
")\n" +
"select v.* from values vl " +
"join items v on v.id = vl.id";
Измените запрос на:
SELECT id, name, properties FROM items where id = ANY($1)
И тогда вы сможете использовать значение параметра List/Set/Array.
Спасибо. Знаете ли вы, как использовать инверсию этого критерия, по сути, предложение NOT IN? Я пытался использовать != ANY($1), но это работает только в том случае, если в переданном списке есть только 1 значение.
ты пробовал NOT (id = ANY ($1))
?
Спасибо, что изучили это, этот вариант не сработал. Я создал отдельный пост SO с дополнительными подробностями, если вы могли бы взглянуть, очень признателен.stackoverflow.com/questions/75509225/…
Этот вариант действительно работал. Ошибка, с которой я столкнулся, была связана с другим запросом. Спасибо за вашу помощь
Большой! Не могли бы вы принять ответ?