Ich experimentiere derzeit mit EJB3 als Vorstudie für ein großes Projekt bei der Arbeit. Eines der Dinge, die ich untersuche, ist das Query-Caching.
Ich habe ein sehr einfaches Domänenmodell mit JPA-Annotationen, einer @Local-Business-Schnittstelle und einer @Stateless-Implementierung in einem EJB-JAR erstellt, das zusammen mit einer sehr einfachen Webapp für einige grundlegende Tests bereitgestellt wird. Die EAR wird in der Standardkonfiguration von JBoss 5.0.1 ohne Änderungen bereitgestellt. Dies war sehr geradlinig und funktionierte wie erwartet.
Mein letzter Test beinhaltete jedoch das Zwischenspeichern von Abfragen, und ich habe einige seltsame Ergebnisse erhalten:
Das hat mich verwirrt, also habe ich Hibernate's show_sql aktiviert, um das Log zu sehen. Uncached und bei der ersten Ausführung mit aktiviertem Cache wird wie erwartet ein SELECT protokolliert. Wenn ich Cache-Treffer erhalten soll, protokolliert Hibernate ein SELECT für jede Zeile in der Datenbanktabelle.
Das würde sicherlich die langsame Ausführungszeit erklären, aber kann mir jemand sagen, warum das passiert?
Der Abfragecache funktioniert so, dass er nur die ID der von der Abfrage zurückgegebenen Objekte zwischenspeichert. Ihre ursprüngliche SELECT-Anweisung kann also alle Objekte zurückgeben, und Hibernate gibt sie Ihnen zurück und erinnert sich an die IDs.
Beim nächsten Ausführen der Abfrage durchläuft Hibernate jedoch die Liste der IDs und stellt fest, dass sie die tatsächlichen Daten materialisieren muss. Also geht es zurück in die Datenbank, um den Rest zu bekommen. Und es macht eine SELECT pro Zeile, die genau das ist, was Sie sehen.
Nun, bevor Sie denken, "diese Funktion ist offensichtlich defekt", liegt der Grund dafür, dass der Query Cache so konzipiert ist, dass er mit dem Second Level Cache zusammenarbeitet. Wenn die Objekte nach der ersten Abfrage im L2-Cache gespeichert werden, sucht Hibernate stattdessen dort nach den Anforderungen für die ID-Anforderung.
Ich empfehle Ihnen dringend, das Buch Java Persistence with Hibernate zu lesen, um mehr darüber zu erfahren . Kapitel 13 behandelt insbesondere die Optimierung von Abfragen und die effektive Verwendung des Caches.