Hibernate Caches


- The first-level cache - Session Level 
- The second-level cache - SessionFactory Level 
- The query cache

The first-level cache

 The first level cache type is the session cacheThe scope of cache objects is of session. Once session is closed, cached objects are gone forever. First level cache is enabled by default and you can not disable it. When we query an entity first time, it is retrieved from database and stored in first level cache associated with hibernate session. If we query same object again with same session object, it will be loaded from cache and no sql query will be executed. The loaded entity can be removed from session using evict() method. The next loading of this entity will again make a database call if it has been removed using evict() method. The whole session cache can be removed using clear() method. It will remove all the entities stored in cache.

The second-level cache

Second level cache is apart from first level cache which is available to be used globally in session factory scope. Above statement means, second level cache is created in session factory scope and is available to be used in all sessions which are created using that particular session factory.
It also means that once session factory is closed, all cache associated with it die and cache manager also closed down.
Further, It also means that if you have two instances of session factory (normally no application does that), you will have two cache managers in your application and while accessing cache stored in physical store, you might get unpredictable results like cache-miss.
  1. Whenever hibernate session try to load an entity, the very first place it look for cached copy of entity in first level cache (associated with particular hibernate session).
  2. If cached copy of entity is present in first level cache, it is returned as result of load method.
  3. If there is no cached entity in first level cache, then second level cache is looked up for cached entity.
  4. If second level cache has cached entity, it is returned as result of load method. But, before returning the entity, it is stored in first level cache also so that next invocation to load method for entity will return the entity from first level cache itself, and there will not be need to go to second level cache again.
  5. If entity is not found in first level cache and second level cache also, then database query is executed and entity is stored in both cache levels, before returning as response of load() method.
  6. Second level cache validate itself for modified entities, if modification has been done through hibernate session APIs.
  7. If some user or process make changes directly in database, the there is no way that second level cache update itself until “timeToLiveSeconds” duration has passed for that cache region. In this case, it is good idea to invalidate whole cache and let hibernate build its cache once again. You can use below code snippet to invalidate whole hibernate second level cache.
Enabling the second level of cache:

  1. <!-- Enable the second-level cache -->  
  2. <property name="cache.use_second_level_cache">true</property>
  3. <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

Disabling the second level of cache:
  1. <!-- Disable the second-level cache -->  
  2. <property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

Cache Strategy using with Annotation as some changes made to the Model class also:
  1. @Cacheable
  2. @Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
  3. @Entity
  4. @Table(name="STUDENT")
  5. public class Student implements Serializable
  6. {

Cache Strategy using with Mapping file *.hbm.xml :
  1. <hibernate-mapping>
  2.    <class name="Student" table="STUDENT">
  3.                This class contains the student detail.
  4.   <cache usage="read-only">
  5.       <id column="ID" name="id" type="java.lang.Long">
  6.          <generator class="native">
  7.       </generator></id>
  8.       <property column="STUDENT_NAME" name="studentName" type="java.lang.String">
  9.       <property column="lCOURSE" name="course" type="java.lang.String">
  10.       <property column="ROLL_NUMBER" name="rollNumber" type="java.lang.Long">
  11.    </property></property></property></cache></class>
  12. </hibernate-mapping>

CONCURRENCY STRATEGIES:

A concurrency strategy is a mediator which responsible for storing items of data in the cache and retrieving them from the cache. If you are going to enable a second-level cache, you will have to decide, for each persistent class and collection, which cache concurrency strategy to use.
  1. Transactional: Use this strategy for read-mostly data where it is critical to prevent stale data in concurrent transactions,in the rare case of an update.
  2. Read-write: Again use this strategy for read-mostly data where it is critical to prevent stale data in concurrent transactions,in the rare case of an update.
  3. Nonstrict-read-write: This strategy makes no guarantee of consistency between the cache and the database. Use this strategy if data hardly ever changes and a small likelihood of stale data is not of critical concern.
  4. Read-only: A concurrency strategy suitable for data which never changes. Use it for reference data only.


Query Cache

The Query Cache is strictly related to Entities, and it draws an association between a search criterion and the Entities fulfilling that specific query filter. The query cache is responsible for caching the results of queries – or to be more precise the keys of the objects returned by queries. By default query cache is disabled, to enable use this property:


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

Links:


Comments

Popular posts from this blog

Getter Template with Optional<> for IntelliJ IDEA

JVM Memory and Tuning

Inversion of Control - Pattern