Second level cache

One benefit of database abstraction layers, such as ORM frameworks, is their ability to transparently cache data:

Caching at the database and application level

The application cache is not an option for many large enterprise applications. With the application cache, we help to reduce many round-trips to get required data from the database cache. The application-level cache stores entire objects, which are retrieved based on hash table keys. Here, we are not going to talk about the application level cache; we are going to talk about the second level cache.

In Hibernate, unlike with the first level cache, the second level cache is SessionFactory scoped; hence, it is shared by all sessions created within the same session factory. When the second level is enabled and the entity is looked up, the following applies:

  1. It will first be checked in the first level cache if the instance is available, and then returned.
  2. If the instance is not present in the first level, it will try to find it in the second level cache, and, if found, it is assembled and returned.
  3. If the instance is not found in the second level cache, it will make the trip to the database and fetch the data. The data is then assembled and returned.

Hibernate doesn't do any caching by itself. It provides the interface org.hibernate.cache.spi.RegionFactory, and cache providers do the implementation of this interface. Here, we will talk about the Ehcache provider, which is mature and the most widely used cache. In order to enable second level caching, we need to add the following two lines to our persistence properties:

hibernate.cache.use_second_level_cache=true
hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory

Once the level two cache is enabled, we need to define which entities we want to cache; we need to annotate those entities with @org.hibernate.annotations.Cache, as follows:

@Entity
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Account implements Serializable {

}

Hibernate uses a separate cache region to store the states of instances of an entity. The region name is the fully qualified class name. There are different concurrency strategies provided by Hibernate, which we can use based on our requirements. The following are the different concurrency strategies:

  • READ_ONLY: Used only for entities that are never modified; in the case of modification, an exception is thrown. It is used for some static reference data that doesn't change.
  • NONSTRICT_READ_WRITE: The cache is updated when the transaction affecting the cached data is committed. While the cache is updated, there is a chance to obtain stale data from the cache. This strategy is suitable for those requirements that can tolerate eventual consistency. This strategy is useful for data that is rarely updated.
  • READ_WRITE: To avoid obtaining stale data while the cache is updated, this strategy uses soft locks. When a cached entity is updated, the entity in the cache is locked and is released after the transaction is committed. All concurrent transactions will retrieve the corresponding data directly from the database.
  • TRANSACTIONAL: The transaction strategy is mainly used in distributed caches in the JTA environment. 

If there is no expiration and eviction policy defined, the cache could grow indefinitely and eventually consume all of the memory. We need to set these policies, and it depends on cache providers. Here, we are using Ehcache, and the following is the method to define expiration and eviction policies in ehcache.xml:

<ehcache>
<cache
name="com.packt.springhighperformance.ch6.bankingapp.model.Account"
maxElementsInMemory="1000" timeToIdleSeconds="0"
timeToLiveSeconds="10"/>
</ehcache>

Many of us think that the cache stores entire objects. However, it doesn't store entire objects, but rather, it stores them in a disassembled state:

  • The primary key is not stored, because it is the cache key
  • Transient properties are not stored
  • Collection associations are not stored by default
  • All property values, except for associations, are stored in their original forms
  • Foreign keys for @ToOne associations are stored only with IDs
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset