Hibernate Second-level-query-caching-Problem mit der gleichen where-Klausel
Meine Anwendung verwendet JPA (1.2), Frühling (3.1.2), Spring Data (1.1.0) und im Ruhezustand (4.1.7).
Datenbank : Oracle10g
Wir haben aktivieren second-level-caching. Es funktioniert gut mit Einheit, sondern es ist die Schaffung Probleme auf named query-caching.
Das Problem ist: Wenn die benannte Abfrage, die hat die gleiche where-Klausel, aber unterschiedliche select-Anweisung, dann, was die erste Abfrage ausführen, gibt es das gleiche Ergebnis für die zweite Abfrage auch.
Wie meine erste Abfrage(countRelease) ist
select count(r) from Release r where r.type in
(select c.contentTypeId from ContentType c where c.parentContentTypeId is NULL)
order by r.validityStart
und zweite Abfrage(findRelease)ist
select r from Release r where r.type in
(select c.contentTypeId from ContentType c where c.parentContentTypeId is NULL)
order by r.validityStart
Wenn die erste Abfrage wird zuerst ausgeführt, dann zählt kommen wird, und danach, wenn ich die zweite Abfrage dann auch zählen wird kommen, es sollte geben Sie mir die Liste der release-Einheit.
Wenn ich entfernen, die Abfrage-cache funktioniert es gut und wenn ich einige änderungen, die in der zweiten Abfrage die where-Klausel dann auch es funktioniert gut, aber ich keine Notwendigkeit, das zu tun.
Wie können wir dieses Problem lösen?
Mein Java-code
@Query(name="findRelease")
@QueryHints({@QueryHint(name = "org.hibernate.cacheRegion", value ="cvodrelease"),@QueryHint(name = "org.hibernate.cacheable", value ="true") })
public List<Release> findRelease();
@Query(name="countRelease")
@QueryHints({@QueryHint(name = "org.hibernate.cacheRegion", value ="cvodrelease"),@QueryHint(name = "org.hibernate.cacheable", value ="true") })
public Long countOfRelease(Date today);
Cache-Konfiguration
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.EhCacheProvider" />
<property name="hibernate.cache.provider_configuration_file_resource_path" value="ehcache.xml" />
<bean id="cacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager" p:cacheManager-ref="ehcache"/>
<bean id="ehcache" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean" p:configLocation="ehcache.xml" p:shared="true"/>
- Kennt einer die Lösung für das oben genannte Problem
- Hat jemand eine Lösung für das oben genannte Problem... oder seine Fehler
- Die
QueryKey
Klasse scheint Speicher den query-string, so ist dies in der Tat merkwürdig. Ich würde setzen Sie einen Haltepunkt aufQueryKey.generateQueryKey()
und versuchen, auf die Spur, warum diequeryString
argument ist das gleiche für die zwei unterschiedlichen Abfragen. - Jain, Es ist besser für Sie post java-code für die überprüfung. code sagt alles. als ich weiß. second-level-cache wirkt sich nicht auf die Abfrage führen. es ist anderes problem.
- Es ist nicht java-code als solche hat Sie nur Methode-Namen mit der @namedQuery, weil wir mithilfe von JPA-Repository
- Es ist java-code, der verwendet die benannten Abfragen...
- Vielleicht ist dies offensichtlich, aber sind Sie sicher, dass Ihre Fragen eindeutige Namen haben? Werden Sie sich bewusst, dass Sie zwei Abfragen mit demselben Namen, in verschiedenen in verschiedenen Klassen definiert werden, werden behandelt, als die gleiche Abfrage.
- Ja meine Abfrage hat verschiedene Namen. Ich bin mir 100% sicher
Du musst angemeldet sein, um einen Kommentar abzugeben.
JPA-1.0-standard hatte keine Zwischenspeicherung enthalten (und JPA 1.2 nicht vorhanden).
JPA-2.0-standard eingeführt caching - einschließlich der Shared-Cache-Speicher ("first level cache" für jeden EntityManagerFactory Instanz) und der Anwendungs-cache (second level cache für ALLE EntityManagerFactor Instanzen). Auch jede PersistenceContext für jeden EntityManager-Instanz fungiert als seine eigene tiefste level-cache - dem "null-level-cache".
Was dies bedeutet ist, dass Ihr Verhalten alle spezifischen, Hibernate 4.1.7 und hat nichts zu tun mit einem standard-oder einem anderen Produkt.
Das ist ein direktes Zitat von Apache OpenJPA docs, nicht Hibernate oder JPA spec. Sie ignorieren können, aber scheint es, wäre es wahr Ruhezustand.
Das ist ein direktes Zitat aus Oracle Kodo JPA-docs, nicht in Hibernate oder JPA spec. Könnte klug sein, dies zu ignorieren.
Das ist ein direktes Zitat aus dem Ruhezustand 4.1 docs. So können Sie diese Ratschläge befolgen - so lange, wie Sie es im Kontext: es ist zu sagen, gehören die second-level-cache-wenn Sie möchten, cache-Einheiten zurückgegeben, die von Abfragen. Wenn Sie nicht möchten, cache gesamte entity-Objekte, sondern wollen einfach nur das Zwischenspeichern der Ergebnisse von NamedQueries mit primitiven Datentypen (Projektionen), dann ist der first level cache ist alles, was Sie brauchen.
Mein Vorschlag:
Ich denke, das problem könnte sein, dass COUNT(r) returns a BigInteger java, die nicht umgewandelt werden-Objekt zum Zwischenspeichern. Sie können rufen Sie addScalar("count", Ruhezustand.LANGE), die auf der Abfrage sagen, hibernate auf eine andere Art - LANGE. Sehen blog.pfa-labs.com/2009/12/caching-raw-sql-count-with-hibernate.html plus Ist/Kann Hibernate die Second-Level-Cache Verwendet werden, für die COUNT () - Operationen?
Den query-cache sollte in der Lage sein, dies zu behandeln. Die second-level-cache sollte nur erforderlich sein, für entity-Objekte.
Sehr vorsichtig sein, Sie verstehen, die lese - /schreib-Verhalten der Objekte, die Sie versuchen, cache - und sicherzustellen, dass die Zahl von liest, ist viel größer als die Anzahl der Schreibvorgänge. Ansonsten caching geben konnte keinen nutzen oder sogar die Dinge verlangsamen, und Dateninkonsistenzen.
Bewusst sein, dass einige JDBC-Treiber die Daten im cache - wenn Ihr es wird sich auf JPA Ergebnisse und JPA wird nicht einmal davon wissen.
Von Mike Keith ' s "Pro JPA 2":
Die meisten [JDBC] - Treiber-cache-verbindungen und Anweisungen. Manche caches auch verfolgen, Tabelle oder Spalte Status, die im wesentlichen transparent, um die JPA-provider, aber dennoch bieten einige Einsparungen in Bezug auf die nicht mit zu gehen, um die Datenbank zu bekommen Daten auf jeden Anruf. Dies ist im Allgemeinen möglich, in der Fahrer nur wenn bekannt ist, dass entweder die Daten schreibgeschützt sind oder der Fahrer steuert den Datenbankzugriff ausschließlich.
JDBC-caching, wenn verfügbar, sollten steuerbar sein über die Konfiguration bestimmte Einstellungen für die Treiber.
EDIT:
In der ersten Abfrage "order by r.validityStart" macht nichts - Sie können es, und alles wird funktionieren.
Den query-cache verwaltet die Ergebnisse, wo die Abfrage zusammen mit Parametern kombiniert, stellt den Schlüssel und den Wert als Bezeichner.
Aus der Dokumentation:
Es ist besser, Holen ganze Objekt, sondern als Felder in der Abfrage.
Möglicherweise es ist die Vernachlässigung der select-Teil der Abfrage & Zwischenspeichern des Ergebnisses.
Der spätere Teil ist der gleiche für beide Abfragen, daher nachgeben, das gleiche Ergebnis. Sie können versuchen, die änderung der Abfrage-Ausführung, um & beobachten Sie das Ergebnis.
Ich glaube, dein problem nicht betreffen second-level-cache - es ist etwas anderes. Der cache selbst kann sich nicht ändern, das erwartete Ergebnis.
Sogar noch sicherer, können Sie versuchen, den folgenden code deaktivieren Sie die second-level-cache vor dem start der zweiten Abfrage:
Wenn das problem weiterhin besteht, dann ist es klar, dass der Second level cache ist nicht der Schuldige.