The JCache API (a.k.a. JSR-107) is a Java specification for temporary, in memory caching of Java objects, including object creation, shared access, spooling, invalidation, and consistency across JVM's.
Ehcache is open source and most widely used java based cache, which can be integrated with popular libraries and frameworks. Ehcache 3.x provides an implementation of JCache specification, which is fully compliant with the JCache API.
In this post, we will learn how to configure the Second-Level cache in Hibernate application using the JCache API with Ehcache’s implementation.
Technologies and tools used for this application are -
- Hibernate 5.2.10.Final
- Ehcache 3.3.1
- JCache API 1.0
- Log4j 2.8.2
- JavaSE 1.8
- Eclipse Neon.3
- Maven 3.3.9
- MySQL 5.7.12
Jar Dependencies
Open
pom.xml
file of your maven project and add the following dependencies in it. <dependencies>
<!-- Mysql Connector -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>6.0.5</version>
</dependency>
<!-- Hibernate 5.2.10 Final -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.2.10.Final</version>
</dependency>
<!-- Hibernate Jcache -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jcache</artifactId>
<version>5.2.10.Final</version>
</dependency>
<!-- Ehcache 3.x -->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.3.1</version>
</dependency>
<!--Log4j2 API -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.8.2</version>
</dependency>
</dependencies>
Hibernate Utility class
To integrate the JCache API and Ehcache with Hibernate, you need to specify the following configuration properties.
1 - Enable second level cache (you can skip this property because default value is
true
for it).hibernate.cache.use_second_level_cache = true
2 - Specify cache region factory class.
hibernate.cache.region.factory_class = org.hibernate.cache.jcache.JCacheRegionFactory
3 - Specify cache provider.
hibernate.javax.cache.provider = org.ehcache.jsr107.EhcacheCachingProvider
Here is the complete example of
HibernateUitl
helper class to bootstrap application.
HibernateUtil.java
package com.boraji.tutorial.hibernate;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.SessionFactory;
import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Environment;
import com.boraji.tutorial.hibernate.entity.Person;
/**
* @author imssbora
*/
public class HibernateUtil {
private static StandardServiceRegistry registry;
private static SessionFactory sessionFactory;
public static SessionFactory getSessionFactory() {
if (sessionFactory == null) {
try {
StandardServiceRegistryBuilder registryBuilder =
new StandardServiceRegistryBuilder();
Map<String, Object> settings = new HashMap<>();
settings.put(Environment.DRIVER, "com.mysql.cj.jdbc.Driver");
settings.put(Environment.URL, "jdbc:mysql://localhost:3306/BORAJI?useSSL=false");
settings.put(Environment.USER, "root");
settings.put(Environment.PASS, "admin");
settings.put(Environment.HBM2DDL_AUTO, "update");
// Enable second level cache (default value is true)
settings.put(Environment.USE_SECOND_LEVEL_CACHE, true);
// Specify cache region factory class
settings.put(Environment.CACHE_REGION_FACTORY,
"org.hibernate.cache.jcache.JCacheRegionFactory");
// Specify cache provider
settings.put("hibernate.javax.cache.provider",
"org.ehcache.jsr107.EhcacheCachingProvider");
registryBuilder.applySettings(settings);
registry = registryBuilder.build();
MetadataSources sources = new MetadataSources(registry)
.addAnnotatedClass(Person.class);
Metadata metadata = sources.getMetadataBuilder().build();
sessionFactory = metadata.getSessionFactoryBuilder().build();
} catch (Exception e) {
if (registry != null) {
StandardServiceRegistryBuilder.destroy(registry);
}
e.printStackTrace();
}
}
return sessionFactory;
}
public static void shutdown() {
if (registry != null) {
StandardServiceRegistryBuilder.destroy(registry);
}
}
}
Entity class
To enable entity caching, annotate entity class with
@Cache
annotation as follow.
Person.java
package com.boraji.tutorial.hibernate.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity
@Table(name = "PERSONS")
@Cache(region = "personCache", usage = CacheConcurrencyStrategy.READ_ONLY)
public class Person implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue
@Column(name = "ID")
private Long id;
@Column(name = "NAME")
private String name;
// Setter and Getter methods
}
Ehcache logging
In this example, we will use the Slf4j API to enable logging for Ehcache and Hibernate.
So, create a
log4j2.xml
file under src/main/resources
folder and write the following code in it.
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration>
<Appenders>
<!-- Console Appender -->
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{yyyy-MMM-dd HH:mm:ss a} [%t] %-5level %logger{36} - %msg%n" />
</Console>
</Appenders>
<Loggers>
<!-- Log SQL statements -->
<Logger name="org.hibernate.SQL" level="debug" additivity="false">
<AppenderRef ref="Console" />
</Logger>
<!-- Log cache -->
<Logger name="org.hibernate.cache" level="debug" additivity="false">
<AppenderRef ref="Console" />
</Logger>
<Logger name="org.ehcache" level="debug" additivity="false">
<AppenderRef ref="Console" />
</Logger>
<Root level="error">
<AppenderRef ref="Console" />
</Root>
</Loggers>
</Configuration>
Run Application
Create the
MainApp
class to test the JCache, Ehcache and Hibernate configuration.
MainApp.java
package com.boraji.tutorial.hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.boraji.tutorial.hibernate.entity.Person;
/**
* @author imssbora
*/
public class MainApp {
public static void main(String[] args) {
Session session = null;
Transaction transaction = null;
try {
//Retrieve the person object from database
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
transaction.begin();
Person person=session.get(Person.class, 1L);
System.out.println(person);
transaction.commit();
session.close();
//Retrieve the person object from cache
session = HibernateUtil.getSessionFactory().openSession();
transaction = session.beginTransaction();
transaction.begin();
Person person2=session.get(Person.class, 1L);
System.out.println(person2);
transaction.commit();
session.close();
} catch (Exception e) {
e.printStackTrace();
}
HibernateUtil.shutdown();
}
}
Output
Reference:
0 komentar: