Master java skills

Second Level Cache

Second level cache is held and maintained by SessionFactory object. It is common for all the session objects that are created from the same SessionFactory object.

Different vendors provide implementation for Second Level Cache in hibernate.

  1. EH Cache
  2. OS Cache
  3. Swarm Cache
  4. JBoss Cache 1.x and JBoss Cache 2

Example

Step 1 : Create a maven project with below dependencies

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javatrainingschool</groupId>
	<artifactId>named-query-example</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<dependencies>
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>6.0.0.Alpha5</version>
		</dependency>
		<dependency>
			<groupId>com.oracle</groupId>
			<artifactId>ojdbc8</artifactId>
			<version>19.3</version>
		</dependency>

		<dependency>
			<groupId>net.sf.ehcache</groupId>
			<artifactId>ehcache</artifactId>
			<version>2.10.8</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-ehcache</artifactId>
			<version>6.0.0.Alpha6</version>
		</dependency>
	</dependencies>


</project>

Step 2 : Create entity class Drink.java

package com.javatrainingschool;

import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;

@Entity
@Table(name = "drink_101")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class Drink {

	@Id
	private int id;
	private String name;
	private String type;
	private boolean alcoholic;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public boolean isAlcoholic() {
		return alcoholic;
	}

	public void setAlcoholic(boolean alcoholic) {
		this.alcoholic = alcoholic;
	}

	@Override
	public String toString() {
		return "Drink [id=" + id + ", name=" + name + ", type=" + type + ", alcoholic=" + alcoholic + "]";
	}

	public Drink(int id, String name, String type, boolean alcoholic) {
		super();
		this.id = id;
		this.name = name;
		this.type = type;
		this.alcoholic = alcoholic;
	}

	public Drink() {
		super();
		// TODO Auto-generated constructor stub
	}

}

Step 3 : Create hibernate.cfg.xml file

<?xml version='1.0' encoding='UTF-8'?>  
<!DOCTYPE hibernate-configuration PUBLIC  
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"  
          "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>

	<session-factory>
		<property name="show_sql">true</property>
		<property name="hbm2ddl.auto">update</property>
		<property name="dialect">org.hibernate.dialect.Oracle9iDialect</property>
		<property name="connection.url">jdbc:oracle:thin:@localhost:1521/xepdb1</property>
		<property name="connection.username">singh</property>
		<property name="connection.password">azad</property>
		<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>

		<property name="cache.use_second_level_cache">true</property>
		<property name="cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>
		<mapping class="com.javatrainingschool.Drink" />


	</session-factory>

</hibernate-configuration>

Step 4 : Create main testing class

package com.javatrainingschool;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;

public class EHCacheMain {

	public static void main(String[] args) {

		StandardServiceRegistry ssr = new StandardServiceRegistryBuilder().configure("hibernate.cfg.xml").build();
		Metadata meta = new MetadataSources(ssr).getMetadataBuilder().build();

		SessionFactory factory = meta.getSessionFactoryBuilder().build();
		
		Session session = factory.openSession();
		
		Transaction t = session.beginTransaction();
		
		Drink drink = new Drink();
		drink.setId(1);
		drink.setName("Iced Tea");
		drink.setType("Cold");
		drink.setAlcoholic(false);
		
		session.save(drink);
		
		t.commit();
		
		session.close();
		
		Session session1 = factory.openSession();

		Drink drink1 = (Drink) session1.load(Drink.class, 1);
		System.out.println(drink1.getId() + " " + drink1.getName() + " " + drink1.getType());
		session1.close();

		Session session2 = factory.openSession();
		Drink drink2 = (Drink) session2.load(Drink.class, 1);
		System.out.println(drink2.getId() + " " + drink2.getName() + " " + drink2.getType());
		session2.close();
		
		factory.close();

	}
}
Output :


Hibernate: insert into drink_101 (alcoholic, name, type, id) values (?, ?, ?, ?)
1 Iced Tea Cold
1 Iced Tea Cold

In the above output, it can be seen that for the first time when Drink entity is loaded, it executes a query into the database, but for the second time, no query is executed. Because the data is fetched from the cache itself.