2 Replies Latest reply on May 27, 2011 10:59 AM by galder.zamarreno

    How to enable JPA L2 entity cache to back the query cache

    timheilman

      When using Hibernate 3.5.6-FINAL as our JPA provider, and infinispan 4.2.0.ALPHA1 as the level-2 query cache provider, I am worried that, contrary to the Hibernate documentation, database results are being stored multiple times in distinct memory locations (for different HQL queries' resultsets that return some of the same records) within the infinispan namedCache, "local-query".  Because many of our frequently-issued queries have a large intersection in their result sets, this could quickly exhaust memory and render the query cache useless.

       

      I suspect I am misconfiguring either infinispan or hibernate or both, as I can't seem to get the hibernate 2nd-level *entity* cache operational as a backing for the query cache.  I would love to see an example of infinispan as a hibernate-as-JPA level-2 query cache whose results are themselves backed by infinispan as a hibernate-as-JPA level-2 *entity* cache.

       

      Details:

       

      Hibernate 3.5 documentation ( http://docs.jboss.org/hibernate/core/3.5/reference/en/html/performance.html#performance-querycache-enable ) claims:

       

      bq. The query cache does not cache the state of the actual entities in the cache; it caches only identifier values and results of value type. For this reaso, [sic] the query cache should always be used in conjunction with the second-level cache for those entities expected to be cached as part of a query result cache

       

      However, enabling the hibernate level-2 query cache using infinispan (per  http://community.jboss.org/wiki/usinginfinispanasjpahibernatesecondlevelcacheprovider) like so in our persistence.xml:

       

                  <property name="hibernate.cache.use_second_level_cache" value="true"/>

                  <property name="hibernate.cache.use_query_cache" value="true"/>

                  <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.InfinispanRegionFactory"/>

                  <property name="hibernate.cache.infinispan.statistics" value="true"/>

       

      and examining the infinispan CacheManager JMX attributes shows only one of the six namedCaches defined in infinispan-configs.xml (from GAV org.hibernate/hibernate-infinispan/3.5.6-FINAL, which depends on GAV org.infinispan/infinispan-core/4.2.0.ALPHA1) gets created, along with one not defined there:

       

          org.hibernate.cache.UpdateTimestampsCache(created)

          timestamps(not created)

          entity-repeatable(not created)

          entity(not created)

          local-query(created)

          replicated-query(not created)

          replicated-entity(not created)

       

      I suspect that the jboss wiki article referenced above, when it discusses the entity cache, is referring to the namedCache "entity"; however, I can't find how to get that cache created.  (Aside: I also worry that infinispan-configs.xml's local-query is created but infinispan-configs.xml's timestamps is not; instead we receive an UpdateTimestampsCache that must be defined elsewhere in hibernate.) Specifying

       

                  <property name="javax.persistence.sharedCache.mode" value="ENABLE_SELECTIVE"/>

       

      in our persistence.xml and then annotating relevant entities @javax.persistence.Cacheable does (according to the infinispan CacheManager JMX attributes) get entity caches created (named as the package-qualified java class name of the entity), but they seem unused even when the JMX statistics show a high hit ratio for local-query (and indeed, spectacular performance for such cache-hitting queries).

       

      Is my fear unfounded and under the covers infinispan is storing an entity's information only once even when it is returned in multiple HQL queries' resultsets?  If not, what is the proper way to get infinispan-configs.xml's namedCache, "entities" used to avoid that duplicate-storage of entity data?  Finally, how can infinispan-configs.xml's namedCache, "timestamps" be used, rather than "org.hibernate.cache.UpdateTimestampsCache", as the hibernate level-2 timestamp cache?

        • 1. How to enable JPA L2 entity cache to back the query cache
          timheilman

          It turns out that my fear was unfounded.   This is indeed operating as indicated by the Hibernate documentation: the query cache is returning only entity identifiers and Hibernate is then assembling those entities individually.

           

          My confusion regarding infinispan-configs.xml's namedCaches, "entity," and, "timestamps," derives only from a false expectation.  Since the namedCache, "local-query," was defined in infinispan-configs.xml, and the CacheManager JMX attributes showed a cache named "local-query" created, I expected that the same would hold for, "timestamps," and, "entity."  This is not so.  These namedCaches will *always* be indicated (not created) in the CacheManager JMX attributes: timetamps, entity, entity-repeatable, replicated-query, and replicated-entity.  Nonetheless the configurations of these namedCaches *are* honored, but the names in the CacheManager JMX attributes will not match, unlike "local-query."  Instead, they will be the cache region name: for timestamps, "org.hibernate.cache.UpdateTimestampsCache," and for entities, the package-qualified java class name of the entity.

           

          I also determined why I was getting no cache hits in the JMX statistics for my level-2 entity cache regions, despite that those regions were correctly backing the query cache.  My test and the application code were set up in such a way that every entity returned in the result sets from the query cache was already in the PersistenceContext aka Session aka Hibernate Level-1 cache, and so during assembly of the result sets due to a query cache hit, they were served from there rather than from the level-2 entity cache regions.

          • 2. Re: How to enable JPA L2 entity cache to back the query cache
            galder.zamarreno

            Information on the internals of 2LC and Infinispan can be found in http://community.jboss.org/docs/DOC-14105 but basically, the naming differences come from the fact that so far we've created a cache per entity type *using the named caches in the config as base*, hence entities are based of "entity" cache. This is likely to change though in the near future to avoid issues with asymmetric clusteers.