Oi,
Em primeiro lugar, obrigado por esta ótima biblioteca.
O erro que estou tendo é o seguinte:
Vinculando uma lista vazia
Nenhuma fábrica de argumento registrada para '[]' do tipo java.util.List
Você pode fornecer mais contexto? Qual SQL você está executando? Qual fornecedor de banco de dados?
Hi @qualidafial ,
Sql: select * from invoice where invoice.id IN :ids
Database vendor: SQL Server 2017
Ok, isso faz sentido agora.
JDBC é um pouco estranho ao trabalhar com matrizes - você precisa saber o nome do tipo de dados usado pelo fornecedor do banco de dados. Para ajudar o Jdbi a conectar os pontos, você deve registrar o nome do tipo de elemento da matriz por nome de classe Java:
Jdbi jdbi = Jdbi.create(...);
...
jdbi.registerArrayType(int.class, "integer");
jdbi.registerArrayType(Integer.class, "integer");
Dito isso, poderíamos melhorar nossas mensagens de exceção para apontar os usuários na direção certa.
@qualidafial Bro, isso é top de linha, muito obrigado!
: +1: Apenas um aviso, poderíamos adicionar um plugin do SQL Server para Jdbi se você puder me indicar alguma documentação para que eu saiba quais tipos de dados personalizados o driver suporta e quais são os mapeamentos entre os tipos Java e o tipo de dados JDBC nomes.
Combinado.
Tipos de dados básicos:
https://docs.microsoft.com/en-us/sql/connect/jdbc/using-basic-data-types
Tipos de dados avançados:
https://docs.microsoft.com/en-us/sql/connect/jdbc/using-advanced-data-types
@qualidafial Para
Você também pode usar @BindList
:
@SqlQuery("select * from invoice where invoice.id IN (<ids>)")
Set<Invoice> getInvoices(@BindList("ids") List<Integer> ids);
Esteja ciente de que diferentes fornecedores de banco de dados podem colocar limites no número de itens permitidos em uma cláusula WHERE column IN (a, b, c, ...)
separada por vírgulas.
Aparentemente, o SQL server só oferece suporte a parâmetros de valor único, então criei o array manualmente; no entanto, isso não é seguro para arrays String e pode introduzir SQL Injection.
default List<LotInvoiceRef> getInvoices(List<Long> invoiceIds) {
final List<LotInvoiceRef> lotInvoiceRefs = invoiceIds.stream()
.map(String::valueOf)
.reduce((a, b) -> a + "," + b)
.map(this::getAllInvoiceRefs)
.orElse(new ArrayList<>());
return lotInvoiceRefs;
}
@georgerb veja meu último comentário, que deve proteger contra injeção de SQL
@qualidafial Eu amo a abordagem @BindList, mas preciso de uma maneira de permitir listas vazias para o parâmetro que @BindList proíbe explicitamente.
@qualidafial nvm, Uma rápida pesquisa na anotação e usei isto: @BindList(value = "invoiceIds", onEmpty = BindList.EmptyHandling.NULL)
e funcionou perfeitamente
Novamente, isso é de primeira qualidade. Existe uma maneira de contribuirmos? pelo menos ajudando vocês com a documentação.
Obrigado, você é muito gentil. Nós: heart: pull requests!
Somente com base nessa conversa, reuni três melhorias possíveis:
@BindList
(e talvez @DefineList
enquanto estivermos no assunto).Se você fizer a gentileza de enviar um problema separado direcionado a cada um dos itens acima. Então podemos fechar este e rastrear cada um isoladamente.
E se você tiver alguma ideia para melhorar o Jdbi com a qual gostaria de executar, faça-o! Os plug-ins JPA, Kotlin e Vavr, bem como muitos elementos do Core e do SQL Object foram todos envios de usuários Jdbi.
@qualidafial done. #993
Obrigado! Encerrando esta questão em favor de # 993
Comentários muito úteis
Ok, isso faz sentido agora.
JDBC é um pouco estranho ao trabalhar com matrizes - você precisa saber o nome do tipo de dados usado pelo fornecedor do banco de dados. Para ajudar o Jdbi a conectar os pontos, você deve registrar o nome do tipo de elemento da matriz por nome de classe Java: