Jeg kan ikke umiddelbart huske, om Hibernate faktisk gemmer PreparedStatement-forekomster selv, eller er afhængig af, at forbindelsesudbyderen genbruger dem. (En hurtig scanning af BatcherImpl foreslår, at den genbruger den sidste PreparedStatement, hvis den udfører den samme SQL flere gange i træk)
Jeg tror, at pointen, som c3p0-dokumentationen forsøger at gøre, er, at for mange JDBC-drivere er et PreparedStatement ikke nyttigt:nogle drivere vil ende med blot at splejse parametrene på klientsiden og derefter sende den indbyggede SQL-sætning til databasen alligevel . For disse drivere er PreparedStatements ingen fordel overhovedet, og enhver indsats for at genbruge dem er spildt. (Postgresql JDBC FAQ siger, at dette var tilfældet for Postgresql før serverprotokol version 3, og der er mere detaljerede oplysninger i dokumentationen).
For drivere, der håndterer PreparedStatements nyttigt, er det sandsynligvis stadig nødvendigt rent faktisk at genbruge PreparedStatement-forekomster for at få nogen fordel. For eksempel hvis føreren implementerer:
- Connection.prepareStatement(sql) - opret en serverside-sætning
- PreparedStatement.execute(..) etc - kør den server-side-sætning
- PreparedStatement.close() - afallokér serverside-sætningen
Givet dette, hvis applikationen altid åbner en forberedt sætning, udfører den én gang og derefter lukker den igen, er der stadig ingen fordel; faktisk kan det være værre, da der nu potentielt er flere rundturer. Så applikationen skal hænge på PreparedStatement-instanser. Selvfølgelig fører dette til et andet problem:Hvis applikationen hænger på for mange, og hver serverside-erklæring bruger nogle ressourcer, kan dette føre til server-side-problemer. I det tilfælde, hvor nogen bruger JDBC direkte, kan dette styres manuelt - nogle udsagn er kendt for at kunne genbruges og er derfor udarbejdet; nogle er det ikke og bruger bare forbigående Statement-forekomster i stedet for. (Dette springer over den anden fordel ved forberedte udsagn:håndtering af argumentudslip)
Så det er grunden til, at c3p0 og andre forbindelsespuljer også har forberedt sætningscacher - det giver applikationskode mulighed for at undgå at håndtere alt dette. Udtalelserne opbevares normalt i en begrænset LRU-pulje, så almindelige udsagn genbruger en PreparedStatement-instans.
De sidste brikker i puslespillet er, at JDBC-chauffører selv kan beslutte at være kloge og gøre dette; og servere kan også selv beslutte at være kloge og opdage en klient, der sender en erklæring, der strukturelt ligner en tidligere.
Da Hibernate ikke selv opbevarer en cache af PreparedStatement-forekomster, skal du have c3p0 til at gøre det for at få gavn af dem. (Som bør reduceres overhead for almindelige udsagn på grund af genbrug af cachelagrede planer). Hvis c3p0 ikke cachelagrer forberedte sætninger, vil driveren bare se, at applikationen forbereder en sætning, udfører den og lukker den igen. Det ser ud til, at JDBC-driveren har en "tærskel"-indstilling for at undgå forberedelse/udførelse af serveroverhead i det tilfælde, hvor applikationen altid gør dette. Så ja, du skal have c3p0 til at lave sætningscache.
Håber det hjælper, undskyld det er lidt langvarigt. Svaret er ja .