Kann ich bei Verwendung von PreparedStatement mit einer einzelnen gemeinsamen Verbindung ohne Pool eine Instanz für jede dml / sql-Operation neu erstellen, die die Leistung vorbereiteter Anweisungen beibehält?
Ich meine:
for (int i=0; i<1000; i++) {
PreparedStatement preparedStatement = connection.prepareStatement(sql);
preparedStatement.setObject(1, someValue);
preparedStatement.executeQuery();
preparedStatement.close();
}
anstatt:
PreparedStatement preparedStatement = connection.prepareStatement(sql);
for (int i=0; i<1000; i++) {
preparedStatement.clearParameters();
preparedStatement.setObject(1, someValue);
preparedStatement.executeQuery();
}
preparedStatement.close();
Meine Frage ergibt sich aus der Tatsache, dass ich diesen Code in eine Multithread-Umgebung stellen möchte. Können Sie mir einen Rat geben? Vielen Dank
java
jdbc
prepared-statement
Stahlfahne
quelle
quelle
sql
ändert sich Ihre Anfrage nicht mit in der Schleife? Wenn sich diese Abfrage nicht für jede Iteration der Schleife ändert, warum erstellen Sie dannPreparedStatement
für jede Iteration eine neue (im ersten Codeausschnitt)? Gibt es einen Grund dafür?Antworten:
Der zweite Weg ist ein bisschen effizienter, aber ein viel besserer Weg ist, sie in Stapeln auszuführen:
Sie sind jedoch abhängig von der Implementierung des JDBC-Treibers, wie viele Stapel Sie gleichzeitig ausführen können. Sie können sie beispielsweise alle 1000 Stapel ausführen:
In Bezug auf Multithread-Umgebungen müssen Sie sich darüber keine Gedanken machen, wenn Sie die Verbindung und die Anweisung im kürzestmöglichen Umfang innerhalb desselben Methodenblocks gemäß der normalen JDBC-Redewendung mithilfe der Anweisung try-with-resources wie in Abbildung gezeigt erwerben und schließen über Schnipsel.
Wenn diese Stapel transaktional sind, möchten Sie die automatische Festschreibung der Verbindung deaktivieren und die Transaktion erst festschreiben, wenn alle Stapel abgeschlossen sind. Andernfalls kann es zu einer fehlerhaften Datenbank kommen, wenn die ersten Stapel erfolgreich waren und die späteren nicht.
quelle
inside the same method block
- Sie meinen, dass jeder Thread seinen eigenen Stapel hat und diese Verbindung und Anweisungen von einer Seite im Stapel sind und von einer anderen Datenquelle für jeden neuen Aufruf von executeFunction (== jeder Thread) eine separate Verbindungsinstanz erhalten. Verstehe ich dich richtig? "Die Schleife in Ihrem Code ist nur ein stark vereinfachtes Beispiel, oder?
Es ist besser, das PreparedStatement nur einmal zu erstellen und es in der Schleife immer wieder zu verwenden.
In Situationen, in denen dies nicht möglich ist (weil es den Programmablauf zu sehr kompliziert hat), ist es immer noch vorteilhaft, ein PreparedStatement zu verwenden, auch wenn Sie es nur einmal verwenden, da die Serverseite der Arbeit (Parsen des SQL und Zwischenspeichern des Ausführungsplan), wird noch reduziert.
Um die Situation zu beheben, in der Sie das Java-seitige PreparedStatement wiederverwenden möchten, verfügen einige JDBC-Treiber (z. B. Oracle) über eine Caching-Funktion: Wenn Sie ein PreparedStatement für dasselbe SQL auf derselben Verbindung erstellen, erhalten Sie dasselbe (zwischengespeicherte) Instanz.
Informationen zu Multithreading: Ich glaube nicht, dass JDBC-Verbindungen über mehrere Threads hinweg gemeinsam genutzt werden können (dh von mehreren Threads gleichzeitig verwendet werden). Jeder Thread sollte seine eigene Verbindung aus dem Pool abrufen, verwenden und erneut in den Pool zurückgeben.
quelle