# Hibernate Caching

* Caching is a facility provided by ORM frameworks which help to have a fast running web application, while helping framework itself to reduce number of queries made to database in a single transaction.
* Hibernate achieves this by implementing caching in two layers, primarily.

## `L1` Cache

* First level cache in hibernate is enabled by default and you do not need to do anything to get this functionality working. In fact, you can not disable it even forcefully.
* Its associated with `Session` object. Session object is created on demand from `SessionFactory` and it is lost, once the session is closed. So, it works in session scope.
* Similarly, first level cache associated with session object is available only till session object is live. It is available to session object only and is not accessible to any other session object in any other part of application.
* Important points
  1. First level cache is associated with session object and other session objects in application can not see it.
  2. The scope of cache objects is of session. Once session is closed, cached objects are gone forever.
  3. First level cache is enabled by default and you can not disable it.
  4. When you 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. _(completely true only for `get()` or `load()`)_.
  5. The loaded entity can be removed from session using `evict()` on object reference. The next loading of this entity will again make a database call if it has been removed using `evict()` method.
  6. The whole session cache can be cleared using `clear()`. It will remove all the entities stored in cache.

## `L2` Cache

* This is different from first level cache which is available to be used globally in session factory scope.
* 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.
* Working of `L2` Cache
  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()`/`get()` call.
  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()`/`get()` 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.
* More about caching can be read [here](https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#caching).
