Eu tenho uma consulta SQL com um parâmetro nomeado :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);"
Quando tento vincular uma lista de Ints ao parâmetro nomeado
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()
}
Eu recebo a seguinte exceção na execução:
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)
Se eu usar .bind("featureIds", 4138)
funciona, portanto, suponho que a nomenclatura esteja correta.
Alguém mais conseguiu isso? Qualquer ajuda é bem-vinda, pois estou totalmente intrigado com isso :(
Ok... Eu tropecei em uma solução ao tentar StringTemplateEngine. Quando coloco o parâmetro para a lista em <>
funciona.
"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)
funciona.
Talvez adicione isso à documentação e forneça um exemplo para bindList
? :)
Sim, bindList realmente expande define <featureIds>
como, por exemplo, :__featureIds_0, :__featureIds_1, ...etc
e vincula os elementos da lista a essas variáveis substitutas.
Se você estiver usando o Postgres, você pode vincular listas como arrays SQL usando where featureIds = any(:featureIds)
na consulta e usando bindByType("featureIds", featureIds, new GenericType<List<Long>>() {})
.
Não para zumbi, mas ao usar bindMap
com um Map<String, Object>
para quem qualquer chave única contém um List
, isso não parece funcionar. Parece que esses parâmetros precisam ser vinculados separadamente do mapa com bindList
. Isso é preciso?
Exemplo:
a,b,c
from
table
where
a = :some_string
and b = ANY(<list_of_strings>)
Com encadernação de:
.bindMap(Map.of(
'some_string', 'foobar',
'list_of_strings', Lists.newArrayList('q', 'r', 's')
))
Irá acionar:
org.jdbi.v3.core.statement.UnableToCreateStatementException: Undefined attribute for token '<list_of_strings>'
Está correto. bindMap
apenas vincula argumentos, enquanto bindList
também precisa definir atributos para que o modelo funcione conforme o esperado. Eles não estão configurados para trabalhar juntos, embora isso possa ser alterado no futuro.
Comentários muito úteis
Ok... Eu tropecei em uma solução ao tentar StringTemplateEngine. Quando coloco o parâmetro para a lista em
<>
funciona."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)
funciona.Talvez adicione isso à documentação e forneça um exemplo para
bindList
? :)