Nepamatuji si, zda Hibernate skutečně ukládá instance PreparedStatement sám nebo se spoléhá na poskytovatele připojení, že je znovu použije. (Rychlé prohledání BatcherImpl naznačuje, že znovu použije poslední PreparedStatement, pokud provádí stejné SQL vícekrát za sebou)
Myslím, že pointa, kterou se dokumentace c3p0 snaží udělat, je ta, že pro mnoho ovladačů JDBC není PreparedStatement užitečný:některé ovladače nakonec jednoduše spojí parametry na straně klienta a pak stejně předají vytvořený SQL příkaz do databáze. . Pro tyto ovladače nejsou PreparedStatements žádnou výhodou a jakékoli úsilí o jejich opětovné použití je zbytečné. (Časté otázky Postgresql JDBC říkají, že to byl případ Postgresql před protokolem serveru verze 3 a v dokumentaci jsou podrobnější informace).
U ovladačů, které zpracovávají PreparedStatement užitečně, je stále pravděpodobně nutné skutečně znovu použít instance PreparedStatement, abyste získali nějaké výhody. Pokud například ovladač implementuje:
- Connection.prepareStatement(sql) – vytvoření příkazu na straně serveru
- PreparedStatement.execute(..) atd. – spusťte tento příkaz na straně serveru
- PreparedStatement.close() – zrušit přidělení příkazu na straně serveru
Vzhledem k tomu, pokud aplikace vždy otevře připravený příkaz, jednou jej provede a poté znovu zavře, stále žádný přínos; ve skutečnosti to může být horší, protože nyní existuje potenciálně více zpátečních cest. Aplikace tedy musí zůstat na instancích PreparedStatement. To samozřejmě vede k dalšímu problému:pokud aplikace visí na příliš velkém počtu a každý příkaz na straně serveru spotřebovává nějaké zdroje, může to vést k problémům na straně serveru. V případě, že někdo používá JDBC přímo, může to být spravováno ručně – je známo, že některé příkazy jsou znovu použitelné, a proto jsou připraveny; některé nejsou a místo toho používají pouze přechodné instance Statement. (Toto přeskakuje další výhodu připravených příkazů:zpracování escapování argumentu)
To je důvod, proč c3p0 a další fondy připojení také připravily mezipaměť příkazů – umožňuje kódu aplikace, aby se s tím vším nezabýval. Příkazy jsou obvykle uchovávány v nějakém omezeném fondu LRU, takže běžné příkazy znovu používají instanci PreparedStatement.
Poslední kousky skládačky jsou v tom, že se řidiči JDBC mohou sami rozhodnout, že budou chytří a udělají to; a servery se také mohou samy rozhodnout, že budou chytré a odhalí klienta, který odesílá prohlášení, které je strukturálně podobné předchozímu.
Vzhledem k tomu, že Hibernate sám neuchovává mezipaměť instancí PreparedStatement, musíte mít c3p0, aby to udělal, abyste je mohli využít. (Což by měla být snížena režie pro běžné příkazy kvůli opětovnému použití plánů uložených v mezipaměti). Pokud c3p0 neukládá připravené příkazy do mezipaměti, ovladač pouze uvidí, jak aplikace připravuje příkaz, provádí jej a pak jej znovu zavře. Vypadá to, že ovladač JDBC má nastavení „práh“, aby se zabránilo režii serveru na přípravu/spouštění v případě, kdy to aplikace vždy dělá. Takže ano, musíte mít c3p0 do mezipaměti příkazů.
Doufám, že to pomůže, omlouvám se, že je to trochu zdlouhavé. Odpověď je ano .