Hi,
Zunächst einmal vielen Dank für diese tolle Bibliothek.
Der Fehler, den ich erfahre, ist der folgende:
Binden einer leeren Liste
Keine Argument-Factory registriert für '[]' vom Typ java.util.List
Können Sie mehr Kontext liefern? Welche SQL führst du aus? Welcher Datenbankanbieter?
Hallo @qualidafial ,
SQL: select * from invoice where invoice.id IN :ids
Datenbankanbieter: SQL Server 2017
Okay, das macht jetzt Sinn.
JDBC ist bei der Arbeit mit Arrays etwas seltsam - Sie müssen den vom Datenbankhersteller verwendeten Datentypnamen kennen. Um Jdbi zu helfen, die Punkte zu verbinden, müssen Sie den Namen des Array-Elementtyps pro Java-Klassennamen registrieren:
Jdbi jdbi = Jdbi.create(...);
...
jdbi.registerArrayType(int.class, "integer");
jdbi.registerArrayType(Integer.class, "integer");
Vor diesem Hintergrund könnten wir unsere Ausnahmemeldungen verbessern, um Benutzern die richtige Richtung zu weisen.
@qualidafial Bro, das ist erstklassig, vielen Dank!
:+1: Nur eine Warnung, wir könnten Jdbi ein SQL Server-Plugin hinzufügen, wenn Sie mich auf eine Dokumentation verweisen können, damit ich weiß, welche benutzerdefinierten Datentypen der Treiber unterstützt und wie die Zuordnungen zwischen Java-Typen und dem JDBC-Datentyp sind Namen.
Austeilen.
Grunddatentypen:
https://docs.microsoft.com/en-us/sql/connect/jdbc/using-basic-data-types
Erweiterte Datentypen:
https://docs.microsoft.com/en-us/sql/connect/jdbc/using-advanced-data-types
@qualidafial Zur Info , anscheinend wird die IN-Anweisung mit einem vorbereiteten SqlArray vom SQL Server JDBC-Treiber nicht unterstützt
Sie können alternativ @BindList
:
@SqlQuery("select * from invoice where invoice.id IN (<ids>)")
Set<Invoice> getInvoices(@BindList("ids") List<Integer> ids);
Beachten Sie, dass verschiedene Datenbankanbieter die Anzahl der zulässigen Elemente in einer durch Kommas getrennten WHERE column IN (a, b, c, ...)
Klausel einschränken können.
Anscheinend unterstützt SQL Server nur Einzelwertparameter, daher habe ich das Array manuell erstellt, dies ist jedoch für String-Arrays unsicher und kann SQL Injection einführen.
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 siehe meinen letzten Kommentar, der vor SQL-Injection schützen soll
@qualidafial Ich liebe den @BindList- Ansatz, aber ich brauche eine Möglichkeit, leere Listen für den Parameter zuzulassen, den
@qualidafial nvm, Ein kurzer Blick in die Anmerkung und ich @BindList(value = "invoiceIds", onEmpty = BindList.EmptyHandling.NULL)
und es hat perfekt funktioniert
Auch dies ist erstklassig. Gibt es eine Möglichkeit, wie wir dazu beitragen können? hilft euch zumindest bei der Dokumentation.
Danke, Du bist sehr freundlich. Wir :heart: Pull-Requests!
Allein aus diesem Gespräch entnehme ich drei mögliche Verbesserungen:
@BindList
(und vielleicht @DefineList
wenn wir schon dabei sind).Wenn Sie so freundlich wären, ein separates Problem zu jedem der oben genannten Themen einzureichen. Dann können wir diesen schließen und jeden einzeln verfolgen.
Und wenn Sie eine Idee zur Verbesserung von Jdbi haben, mit der Sie arbeiten möchten, tun Sie es bitte! Die JPA-, Kotlin- und Vavr-Plugins sowie viele Elemente von Core und SQL Object wurden alle von Jdbi-Benutzern eingereicht.
@qualidafial erledigt. #993
Vielen Dank! Schließe diese Ausgabe zu Gunsten von #993
Hilfreichster Kommentar
Okay, das macht jetzt Sinn.
JDBC ist bei der Arbeit mit Arrays etwas seltsam - Sie müssen den vom Datenbankhersteller verwendeten Datentypnamen kennen. Um Jdbi zu helfen, die Punkte zu verbinden, müssen Sie den Namen des Array-Elementtyps pro Java-Klassennamen registrieren: