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 :(
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.
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? :)