4 Replies Latest reply on Feb 2, 2011 6:47 AM by sannegrinovero

    Lots Of Puts But No Hits

    k1100t

      I'm trying to setup Infinispan as the 2LC for my JPA provider (Hibernate) in a JBoss, but I don't know if it's configured correctly. Looking at the statistics provided to the /admin-console app, I'm getting plenty of puts, but no hits.  Is there some logging or other debugging I can turn on to see what's in the cache and what it's trying to match on...?

       

      My application is trivial, as I'm just trying to understand everything and get it all working, befiore rolling it out into our main application.

       

      My <tt>persistence.xml</tt> is:

       

      <persistence xmlns="http://java.sun.com/xml/ns/persistence"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
                   version="2.0">
      
        <persistence-unit name="RequestLogPU">
          <provider>org.hibernate.ejb.HibernatePersistence</provider>
          <jta-data-source>java:/PostgresDS</jta-data-source>
          <shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
          <properties>
            <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
            <property name="hibernate.connection.release_mode" value="after_statement" />
      
            <property name="hibernate.c3p0.min_size" value="1" />
            <property name="hibernate.c3p0.max_size" value="100" />
            <property name="hibernate.c3p0.timeout" value="300" />
            <property name="hibernate.c3p0.max_statements" value="100" />
      
            <property name="hibernate.default_batch_fetch_size" value="8" />
            <property name="hibernate.default_schema" value="public" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
            <property name="hibernate.format_sql" value="false" />
            <property name="hibernate.generate_statistics" value="true" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
      
            <property name="hibernate.max_fetch_depth" value="1" />
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.use_sql_comments" value="true" />
      
            <property name="hibernate.cache.use_second_level_cache" value="true" />
            <property name="hibernate.cache.use_query_cache" value="true" />
            <property name="hibernate.cache.infinispan.statistics" value="true" />
            <property name="hibernate.cache.infinispan.cachemanager" value="java:CacheManager/entity" />
            <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.JndiInfinispanRegionFactory" />
            <property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
          </properties>
        </persistence-unit>
      
      </persistence>
      

       

      The entity I'm trying to cache is:

       

      @Entity
      @Cacheable
      @NamedQueries({
          @NamedQuery(
              name = "countLoggedRequests",
              query = "SELECT count(x) FROM LoggedRequest x"
          ),
          @NamedQuery(
              name = "getLoggedRequest",
              query = "SELECT x FROM LoggedRequest x WHERE x.id = :id"
          )
      })
      public class LoggedRequest implements Serializable {
      
          private static final long serialVersionUID = -5235540047877931824L;
      
          @Id
          @GeneratedValue(strategy = GenerationType.AUTO)
          private Long id;
      
          private String sessionId;
      
          private String tracker;
      
          private String remoteIp;
      
          private String date;
      
          public LoggedRequest() {
              super();
          }
      
          public LoggedRequest(final String sessionId, final String tracker, final String remoteIp, final String date) {
              this.sessionId = sessionId;
              this.tracker = tracker;
              this.remoteIp = remoteIp;
              this.date = date;
          }
      
          // Bean accessors deleted for brevity...
      
      
      }
      

       

      Essentially, I chuck a load of HTTP request information into a database table and then I have a JSP page that via AJAX and a EJB grabs a random table row and appends it to a table. You can clearly see duplicate rows in the table where the the, not so, random row selection has thrown back the same rowm Now, I would have thought that in the case of it returning an entity that it's already returned, it would have pulled it from the 2LC and thus I'd see a hit in the stats? Or am I barking up the wrong tree here?

       

      Cheers,

        • 1. Re: Lots Of Puts But No Hits
          sannegrinovero

          From your stats, it seems it's configured as you have put operations, but you also have zero misses so nobody ever tried to load something from the cache.

          How are you loading LoggedRequest? if you're using the named queries you've shown, it doesn't seem you enabled those queries to be cacheable. Hibernate is very conservative about enabling caches.

          • 2. Lots Of Puts But No Hits
            k1100t

            So having <property name="hibernate.cache.use_query_cache" value="true" /> doesn't cause the named queries to be cached then...? How do I go about telling Hibernate to to cache them...?

             

            Cheers,

            • 3. Re: Lots Of Puts But No Hits
              k1100t

              So putting @Cacheable on your entitity and setting <property name="hibernate.cache.use_query_cache" value="true" /> in your persistance.xml file isn't enough, you also have to specify a query hint in the named query definition, like thus:

               

              @NamedQueries({
                  @NamedQuery(
                      name = "countLoggedRequests",
                      query = "SELECT count(x) FROM LoggedRequest x"
                  ),
                  @NamedQuery(
                      name = "getLoggedRequest",
                      query = "SELECT x FROM LoggedRequest x WHERE x.id = :id",
                      hints = {
                          @QueryHint(
                              name="org.hibernate.cacheable",
                              value="true"
                          )
                      }
                  )
              })
              

               

              I am now getting cache hits and misses, along with my puts.

               

              Cheers,

               

              Message was edited by: Bob Arnott; corrected a few spelling mistakes.

              • 4. Lots Of Puts But No Hits
                sannegrinovero

                Exactly, that's the solution via JPA annotations. Using Hibernate Annotation org.hibernate.annotations.NamedQuery you have explicit cache options and some more control; personally while using JPA for almost all applications I use Hibernate's NamedQuery annotation instead for this reason. hibernate.cache.use_query_cache=true enabled the query cache service, you still have to choose which queries you want to cache, as likely you won't cache all of them.