Jag minns inte direkt om Hibernate faktiskt lagrar PreparedStatement-instanser själv, eller litar på att anslutningsleverantören återanvänder dem. (En snabb genomsökning av BatcherImpl föreslår att den återanvänder den senaste PreparedStatement om samma SQL körs flera gånger i rad)
Jag tror att poängen som c3p0-dokumentationen försöker få fram är att för många JDBC-drivrutiner är en PreparedStatement inte användbar:vissa drivrutiner kommer att sluta med att helt enkelt splitsa parametrarna på klientsidan och sedan skicka den byggda SQL-satsen till databasen ändå. . För dessa förare är PreparedStatements ingen fördel alls, och alla ansträngningar att återanvända dem är bortkastade. (Postgresql JDBC FAQ säger att detta var fallet för Postgresql före serverprotokollet version 3 och det finns mer detaljerad information i dokumentationen).
För drivrutiner som hanterar PreparedStatements på ett användbart sätt är det troligen fortfarande nödvändigt att faktiskt återanvända PreparedStatement-instanser för att få någon nytta. Till exempel om föraren implementerar:
- Connection.prepareStatement(sql) - skapa en server-side-sats
- PreparedStatement.execute(..) etc - exekvera den serverside-satsen
- PreparedStatement.close() - avallokera serversidesatsen
Med tanke på detta, om applikationen alltid öppnar en förberedd sats, kör den en gång och sedan stänger den igen, finns det fortfarande ingen fördel; i själva verket kan det vara värre eftersom det nu potentiellt finns fler tur- och returresor. Så applikationen måste hänga på PreparedStatement-instanser. Naturligtvis leder detta till ett annat problem:om applikationen hänger på för många, och varje server-side statement förbrukar vissa resurser, då kan detta leda till server-side problem. I det fall någon använder JDBC direkt, kan detta hanteras för hand - vissa uttalanden är kända för att kunna återanvändas och är därför förberedda; vissa är det inte och använder bara tillfälliga Statement-instanser istället. (Detta är att hoppa över den andra fördelen med förberedda uttalanden:hantering av argument escapeing)
Så det är därför som c3p0 och andra anslutningspooler också har förberedda satscacher - det tillåter applikationskod att undvika att hantera allt detta. Utlåtandena förvaras vanligtvis i en begränsad LRU-pool, så vanliga uttalanden återanvänder en PreparedStatement-instans.
De sista pusselbitarna är att JDBC-förare själva kan bestämma sig för att vara smarta och göra detta; och servrar kan också själva besluta sig för att vara smarta och upptäcka en klient som skickar ett uttalande som strukturellt liknar en tidigare.
Med tanke på att Hibernate inte själv har en cache av PreparedStatement-instanser, måste du ha c3p0 att göra det för att dra nytta av dem. (Vilket bör reduceras omkostnader för vanliga uttalanden på grund av återanvändning av cachade planer). Om c3p0 inte cachelagrar förberedda satser, kommer föraren bara att se programmet förbereda en sats, köra den och sedan stänga den igen. Det verkar som att JDBC-drivrutinen har en "tröskel"-inställning för att undvika att förbereda/köra serveroverhead i det fall applikationen alltid gör detta. Så, ja, du måste ha c3p0 för att cachelagra uttalanden.
Hoppas det hjälper, förlåt att det är lite långdraget. Svaret är ja .