Ich erinnere mich nicht sofort, ob Hibernate die PreparedStatement-Instanzen tatsächlich selbst speichert oder sich auf den Verbindungsanbieter verlässt, um sie wiederzuverwenden. (Ein schneller Scan von BatcherImpl legt nahe, dass es das letzte PreparedStatement wiederverwendet, wenn dasselbe SQL mehrmals hintereinander ausgeführt wird)
Ich denke, der Punkt, den die c3p0-Dokumentation zu machen versucht, ist, dass für viele JDBC-Treiber ein PreparedStatement nicht nützlich ist:Einige Treiber werden am Ende einfach die Parameter auf der Client-Seite spleißen und dann die erstellte SQL-Anweisung trotzdem an die Datenbank übergeben . Für diese Treiber sind PreparedStatements überhaupt kein Vorteil, und jeder Aufwand, sie wiederzuverwenden, ist verschwendet. (Die Postgresql JDBC FAQ besagt, dass dies für Postgresql vor der Version 3 des Serverprotokolls der Fall war, und es gibt detailliertere Informationen in der Dokumentation).
Für Treiber, die PreparedStatements sinnvoll handhaben, ist es wahrscheinlich immer noch notwendig, PreparedStatement-Instanzen tatsächlich wiederzuverwenden, um Vorteile zu erzielen. Zum Beispiel, wenn der Treiber implementiert:
- Connection.prepareStatement(sql) - erstellt eine serverseitige Anweisung
- PreparedStatement.execute(..) etc - führt diese serverseitige Anweisung aus
- PreparedStatement.close() - Zuordnung der serverseitigen Anweisung aufheben
Wenn also die Anwendung immer eine vorbereitete Anweisung öffnet, sie einmal ausführt und dann wieder schließt, bleibt immer noch kein Vorteil; Tatsächlich könnte es noch schlimmer sein, da es jetzt möglicherweise mehr Hin- und Rückfahrten gibt. Die Anwendung muss sich also an PreparedStatement-Instanzen halten. Dies führt natürlich zu einem weiteren Problem:Wenn die Anwendung an zu vielen hängen bleibt und jede serverseitige Anweisung einige Ressourcen verbraucht, kann dies zu serverseitigen Problemen führen. In dem Fall, in dem jemand JDBC direkt verwendet, könnte dies durch handliche Anweisungen verwaltet werden – einige Anweisungen sind bekanntermaßen wiederverwendbar und werden daher vorbereitet; Einige sind es nicht und verwenden stattdessen nur vorübergehende Statement-Instanzen. (Dies überspringt den anderen Vorteil von vorbereiteten Anweisungen:Umgang mit Argument-Escapezeichen)
Aus diesem Grund verfügen c3p0 und andere Verbindungspools auch über vorbereitete Anweisungs-Caches – damit kann der Anwendungscode vermeiden, sich mit all dem zu befassen. Die Anweisungen werden normalerweise in einem begrenzten LRU-Pool gespeichert, sodass allgemeine Anweisungen eine PreparedStatement-Instanz wiederverwenden.
Die letzten Teile des Puzzles sind, dass JDBC-Treiber selbst entscheiden können, schlau zu sein und dies zu tun; und Server können sich auch selbst entscheiden, schlau zu sein und einen Client entdecken, der eine Erklärung abgibt, die einer vorherigen strukturell ähnlich ist.
Da Hibernate selbst keinen Cache von PreparedStatement-Instanzen speichert, müssen Sie c3p0 dazu bringen, dies zu tun, um davon profitieren zu können. (Was den Overhead für allgemeine Anweisungen aufgrund der Wiederverwendung von zwischengespeicherten Plänen reduzieren sollte). Wenn c3p0 keine vorbereiteten Anweisungen zwischenspeichert, sieht der Treiber nur, wie die Anwendung eine Anweisung vorbereitet, sie ausführt und sie dann wieder schließt. Sieht so aus, als hätte der JDBC-Treiber eine "Schwellenwert"-Einstellung, um den Aufwand für das Vorbereiten/Ausführen des Servers zu vermeiden, falls die Anwendung dies immer tut. Also, ja, Sie müssen c3p0 das Zwischenspeichern von Anweisungen durchführen lassen.
Hoffe das hilft, sorry ist etwas langatmig. Die Antwort ist Ja .