Jdbi: BindList kann meinen benannten Parameter in der Abfrage nicht finden und löst eine Ausnahme aus

Erstellt am 1. Feb. 2018  ·  4Kommentare  ·  Quelle: jdbi/jdbi

Ich habe eine SQL-Abfrage mit einem benannten Parameter :featureIds

const val selectGeoCoordinates = "SELECT gg.feature_id, gg.latitude, gg.longitude, gg.order, gg.group FROM geo.geo_coordinates as gg WHERE gg.feature_id IN (:featureIds);"

Wenn ich versuche, eine Liste von Ints an den benannten Parameter zu binden

val values: List<Int> = listOf(4138, 1752, 1161, 371, 1860, 5498)
val geoCoordinatesList = geo.withHandle<List<GeoCoordinates>, Exception> { handle ->
                handle.createQuery(selectGeoCoordinates).bindList("featureIds", values)
                        .mapTo<GeoCoordinates>().list()
            }

Ich erhalte die folgende Ausnahme bei der Ausführung:

    Caused by: org.jdbi.v3.core.statement.UnableToExecuteStatementException: Unable to execute, no named parameter matches 'featureIds'. [statement:"SELECT gg.feature_id, gg.latitude, gg.longitude, gg.order, gg.group FROM geo.geo_coordinates as gg WHERE gg.feature_id IN :featureIds ;", rewritten:"SELECT gg.feature_id, gg.latitude, gg.longitude, gg.order, gg.group FROM geo.geo_coordinates as gg WHERE gg.feature_id IN :featureIds ;", parsed:"ParsedSql{sql='SELECT gg.feature_id, gg.latitude, gg.longitude, gg.order, gg.group FROM geo.geo_coordinates as gg WHERE gg.feature_id IN ? ;', parameters=ParsedParameters{positional=false, parameterNames=[featureIds]}}", arguments:{ positional:{}, named:{__featureIds_0:4138,__featureIds_4:1860,__featureIds_3:371,__featureIds_2:1161,__featureIds_1:1752,__featureIds_5:5498}, finder:[]}]
    at org.jdbi.v3.core.statement.ArgumentBinder.lambda$bindNamed$0(ArgumentBinder.java:58)
    at java.util.Optional.orElseThrow(Optional.java:290)
    at org.jdbi.v3.core.statement.ArgumentBinder.bindNamed(ArgumentBinder.java:57)
    at org.jdbi.v3.core.statement.ArgumentBinder.bind(ArgumentBinder.java:27)
    at org.jdbi.v3.core.statement.SqlStatement.internalExecute(SqlStatement.java:1443)
    at org.jdbi.v3.core.result.ResultProducers.lambda$getResultSet$2(ResultProducers.java:59)
    at org.jdbi.v3.core.result.ResultIterable.lambda$of$0(ResultIterable.java:53)
    at org.jdbi.v3.core.result.ResultIterable.stream(ResultIterable.java:141)
    at org.jdbi.v3.core.result.ResultIterable.collect(ResultIterable.java:197)
    at org.jdbi.v3.core.result.ResultIterable.list(ResultIterable.java:186)

Wenn ich .bind("featureIds", 4138) verwende, funktioniert es, daher gehe ich davon aus, dass die Benennung korrekt ist.

Hat das noch jemand? Jede Hilfe ist willkommen, da ich total verwirrt bin :(

Hilfreichster Kommentar

Okay ... Ich bin beim Ausprobieren von StringTemplateEngine über eine Lösung gestolpert. Wenn ich den Parameter für die Liste in <> setze, funktioniert es.
"SELECT gg.feature_id, gg.latitude, gg.longitude, gg.order, gg.group FROM geo.geo_coordinates as gg WHERE gg.feature_id IN (<featureIds>);"

.bindList("featureIds", values) funktioniert.

Vielleicht fügen Sie dies der Dokumentation hinzu und geben ein Beispiel für bindList an? :)

Alle 4 Kommentare

Okay ... Ich bin beim Ausprobieren von StringTemplateEngine über eine Lösung gestolpert. Wenn ich den Parameter für die Liste in <> setze, funktioniert es.
"SELECT gg.feature_id, gg.latitude, gg.longitude, gg.order, gg.group FROM geo.geo_coordinates as gg WHERE gg.feature_id IN (<featureIds>);"

.bindList("featureIds", values) funktioniert.

Vielleicht fügen Sie dies der Dokumentation hinzu und geben ein Beispiel für bindList an? :)

Yep, bindList erweitert tatsächlich definiert <featureIds> als zB :__featureIds_0, :__featureIds_1, ...etc und bindet die Listenelemente an diese Ersatzvariablen.

Wenn Sie Postgres verwenden, können Sie Listen als SQL-Arrays mit where featureIds = any(:featureIds) in der Abfrage und mit bindByType("featureIds", featureIds, new GenericType<List<Long>>() {}) binden.

Nicht für Zombies, aber wenn Sie bindMap mit einem Map<String, Object> verwenden, für das ein einzelner Schlüssel ein List enthält, scheint dies nicht zu funktionieren. Es scheint, dass solche Parameter getrennt von der Karte mit bindList gebunden werden müssen. Ist das richtig?

Beispiel:

  a,b,c
from
  table
where
  a = :some_string
  and b = ANY(<list_of_strings>)

Mit einer Bindung von:

.bindMap(Map.of(
  'some_string', 'foobar',
  'list_of_strings', Lists.newArrayList('q', 'r', 's')
))

Wird auslösen:

org.jdbi.v3.core.statement.UnableToCreateStatementException: Undefined attribute for token '<list_of_strings>' 

Das ist richtig. bindMap bindet nur Argumente, während bindList auch Attribute definieren muss, damit das Templating wie erwartet funktioniert. Sie sind nicht darauf ausgelegt, zusammenzuarbeiten, obwohl sich das möglicherweise in Zukunft ändern könnte.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

jimmyhmiller picture jimmyhmiller  ·  6Kommentare

rherrmann picture rherrmann  ·  4Kommentare

stevenschlansker picture stevenschlansker  ·  4Kommentare

kkrgwbj picture kkrgwbj  ·  4Kommentare

mcarabolante picture mcarabolante  ·  4Kommentare