Ich weiß, dass die Verwendung von vorbereiteten Anweisungen hilft, SQL-Injektion zu vermeiden. Mein Problem ist, dass eine vorbereitete Aussage normalerweise sehr statisch ist. Ich habe ein Problem, wo ich die Where-Klausel der SQL-Abfrage zur Laufzeit, abhängig von Benutzereingaben erstellen. Abhängig davon, welche Eingabefelder gefüllt sind, muss ich die entsprechenden Anweisungen zum Where-Klausel hinzufügen. Wie kann dies mit vorbereiteten Aussagen realisiert werden?Wie erstellt man eine dynamische vorbereitete Anweisung in Java?
Antwort
Ich denke, dass Sie Ihre vorbereiteten Anweisungen basierend auf den Spalten, die sie abfragen möchten, dynamisch erstellen können, d. H. Mit einem StringBuffer und einer Schleife, um sie basierend auf den erforderlichen Spalten zu erstellen.
Für Effizienz sollten Sie diese in einer Art In-Memory-Lookup halten. Sie erhalten also eine Map oder eine andere Sammlung von vorbereiteten Anweisungen, bei denen der Abfrageschlüssel die Spalten ist, für die Abfragen erstellt werden sollen.
Wenn Sie nur den Schutz vor sql-injection wünschen, ist das Erstellen der Abfrage zur Laufzeit OK, solange Sie nichts in die Abfrage gesendete Benutzer einfügen (aber eine Klausel einfügen, wenn der Benutzer mindestens etwas in das Feld gesendet hat) OK).
Leistung - ich weiß es nicht. Vielleicht wird die DB vorbereitete Anweisungen zwischenspeichern, wenn Sie also genau das gleiche erneut erstellen, wird es schneller, oder es wird nicht. Ich weiß nicht, wie ich es herausfinden soll.
Von den JavaDocs for PreparedStatement "Ein Objekt, das eine vorkompilierte SQL-Anweisung darstellt." Darauf basierend würde ich der DB nicht trauen, sie zu cachen, ich würde es vorziehen, sie selbst zu cachen. Natürlich könntest du das immer profilieren.Aber es wäre wahrscheinlich schneller, nur den Cache zu implementieren;) – Jonathan
http://www.theserverside.com/news/1365244/Why-Prepared-Statements-are-important-and-how-use-them- Das Caching kann ordnungsgemäß über den Verbindungspool erfolgen. – Alpedar
Wenn Sie Hibernate verwenden, ist Criteria Queries API ein nettes Tool zum Vermeiden von String-Verkettung zum Erstellen von SQL-Abfragen. Mit JDBC einfach, müssen Sie mit einem StringBuffer gehen, wie @Jhonatan sagte.
Wenn Sie die Where/and-Klausel (en) in Ihrer Abfrage basierend auf den vom Benutzer ausgewählten Optionen erstellen, nehme ich an, dass Sie bereits wissen, welche Änderungen an der Abfrage vorgenommen werden müssen Holen Sie sich die gewünschten Daten. Wenn dies der Fall ist, können Sie eine Methode erstellen, die die Option übernimmt, nach der der Benutzer als Parameter für die Methode gefragt hat. Die Methode erstellt die Abfrage und gibt diese Abfrage zurück.
//something similar to the following
public String buildQuery(int option){
StringBuilder sb = new StringBuilder();
sb.append("select fields from table");
switch(option){
case 1:
//build query and append to sb
sb.append("where clause for option1");
case 2:
//build query and append to sb
sb.append("where clause for option2");
default:
// build query using default
sb.append("default where clause");
}
return sb.toString();
}
// create the stored procedure
PreparedStatement ps = conn.prepareStatement(buildQuery(2));
ResultSet rs = ps.executeQuery();
Nun, wenn Sie bestimmte Benutzer eingegebenen Werte in der Abfrage verwenden, müssen Sie sie vorübergehend in einer Liste speichern oder Karte und setzen sie dann.
ps.setString(1,list.get(0));
ps.setString(2,list.get(1));
ResultSet rs = ps.executeQuery();
Es gibt probbaly eine elegeant Lösung für das Problem, aber wir haben eine Anwendung, die die Datenbank für die Datensätze anhand der Benutzereingabe, die Abfragen erstellen abfragt und es hat sich in den letzten zwei Jahren arbeitet gut. Ich hoffe, das hilft.
Deklarieren Sie eine Methode und übergeben Sie die Benutzereingabe über diese Methode. Verwenden Sie dann setString
oder setLong
Je nach Eingangsdatentyp innerhalb des preparedstement Objekt.
OK, aber das bedeutet auch, ich muss auch die Liste der Parameter mit meiner erstellten SQL-Abfrage behalten, weil das Hinzufügen von Werten nur mit Indizes möglich ist. Habe ich recht? – Mnementh
Ja, Sie müssen die Namen der Parameterspalten behalten, um eine Suche in Ihrem Cache durchzuführen. Sie müssen auch ihre Reihenfolge beibehalten oder die Reihenfolge vorhersagen (alphabetisch?), Damit Sie wissen, welches "?" mit Ihren Abfragedaten ersetzen. Hoffe, das ist alles macht Sinn, SQL nicht meine erste Sprache ist :) – Jonathan
Niot so einfach wie ich gehofft, aber überschaubar. Vielen Dank. – Mnementh