Database operations are typically very expensive. A typical query would have to be first transmitted over the network. The database has to create a query plan for it and then execute it. The response then has to be transmitted over the network again before the client can process the results. Most databases will cache the results and some will cache queries thereby preventing the execution of the queries and sometimes eliminate the need for the query plan. But these are largely dependent on the number of unique queries and the network overhead is still there.
The natural and obvious answer is to have a cache at the client end of the database connection. Hibernateprovides one cache (the first-level cache) through which all requests must pass. A second-level cache is optional and configurable.
The L1 cache ensures that within a session the request for a object from the database always returns the same object instance hence preventing the object from being reloaded. You can always use object.evict() to discard the object and force a reload.To discard all objects in a session you can issue session.clear().This can also be called called a Java Virtual Machine (JVM) or SessionFactory-level class. . If you have a second-level cache at the SessionFactory level, the application objects are cached in a manner where they are available across sessions.
The L2 cache also called as query cache is external to hibernate . Hibernate provides a pluggable interface for the L2 cache. This allows a cache to be shared between applications on the same machine or even between multiple applications on multiple machines. The L2 cache will not be able to react to changes made by an external application so you have to be careful not to lose the state of the data. Also a distributed cache creates lot of network traffic and takes up memory as well.
Java threads do not timeout when there is a deadlock so don’t share sessions between different threads. If you absolutely must maintain an instance for a longer duration, maintain the instance within a ThreadLocal object. For most purposes, however, the lightweight nature of the Session object makes it practical to construct, use, and destroy an instance, rather than to store a session.
Some of the widely used L2 cache implementations are
EHCache
An in-process cache which is not cluster safe but supports Query Cache. It can use memory as well as disk.
OSCache
An in-process cache which is not cluster safe but supports Query Cache. It can use memory as well as disk.
SwarmCache
A multicast distributed cache which is cluster safe(clustered invalidation) but does not support Query Cache.
TreeCache
A multicast distributed transactional cache which is cluster safe but does not support Query Cache.
Configuration of EH Cache
When the objects being cached need to be updated, the read-write usage mechanism is an appropriate option to choose. If you use database imports or have an alternate way to update the database this option will not be suitable. It becomes even more difficult if the cache is clustered. The database has to be locked for the cache and the database to be in sync.
The nonstrict read-write cache is the same as read write except that it writes to the database occasionally.
The following properties are available in the Hibernate Configuration files to handle cache setup:
hibernate.cache.use_minimal_puts: Optimizes second-level cache operation to minimize writes, at the cost of more frequent reads (useful for clustered caches). Possible values are true and false.
hibernate.cache.use_query_cache: Enables the query cache. The query cache is disabled by default. Possible values are true and false.
Example
Session session = SessionFactory.openSession();
Query query = session.createQuery(”from Users”);
query.setCacheable(true);
List users = query.list();
SessionFactory.closeSession();
To explictly use EHCache :
Add this property to the hibernate .cfg.xml
<property name="hibernate.cache.provider_class">net.sf.ehcache.hibernate
.Provider</property>
Create a file ehcache.xml and make sure it is available in the classpath
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"
/>
<cache name="example.survey.Survey"
maxElementsInMemory="1000"
eternal="false"
timeToIdleSeconds="3600"
overflowToDisk="true"
/>
<cache name="example.survey"
maxElementsInMemory="1000"
eternal="true"
overflowToDisk="true"
/>
</ehcache>
timeToIdleSeconds specifies how long an object can be idle before it expires. The timeToLiveSecondsvalue specifies the overall length of time that an object can be cached before being expired.
When not to use Cache
1) When the database can be modified by an external source. You may be able to deal with this issue by specifying a version or timestamp property for your object and using the Session.lock() method to verify that the object hasn’t been changed.
2)Caching only helps when the same data is used multiple times within the expiry time period. There is no point in caching data which expires before it can be used.
3)In financial applications where auditing is very important.
4)When the dataset is too large
5) when you don’t know what the hell you are doing ![]()
