Configuring Hibernate with Spring MVC

Syed Hasan
4 min readFeb 10, 2020

In this post I will demonstrate how to configure Hibernate 5 to Spring MVC project. We will modify our existing Service classes written in Spring JDBC.

  1. Adding Dependencies

To begin with, we will add required dependencies to our project. The list of dependencies are as follows. Please make sure you use the updated versions of following dependencies.

<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>5.3.11.Final</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.10.2</version>
</dependency>

<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
<!-- We will need the following dependency for scanning @Entity annotated classes --><dependency>
<groupId>org.reflections</groupId>
<artifactId>reflections</artifactId>
<version>0.9.12</version>
</dependency>

2. Configuration

Now we will write our configurations for using Hibernate provided features. To use hibernate, we will add a hibernate.properties file in resources folder.

hibernate.hbm2ddl.auto=update
hibernate.dialect
=org.hibernate.dialect.MySQL5Dialect
hibernate.show_sql
=true
#JDBC Connection Properties
hibernate.connection.url
=jdbc:mysql://localhost:3306/student_course_module_jpa?createDatabaseIfNotExist=true&serverTimezone=UTC
hibernate.connection.driver_class
=com.mysql.cj.jdbc.Driver
hibernate.connection.username
=root
hibernate.connection.password
=

The beans we need are:

a) SessionFactoryBean

@Bean
public SessionFactory createAndGetLocalSessionFactoryBean() {
if (this.sessionFactory == null) {
try {
Configuration configuration = new Configuration();
// Hibernate settings equivalent to hibernate.cfg.xml's properties
Properties settings = getBuiltProperties("hibernate.properties");

configuration.setProperties(settings);
configuration.addPackage("com.spring5.practice.model");
for (Class<?> clazz : (new Reflections("com.spring5.practice.model")).getTypesAnnotatedWith(Entity.class)) {
if (!Modifier.isAbstract(clazz.getModifiers())) {
configuration.addAnnotatedClass(clazz);
}
}
StandardServiceRegistryBuilder serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(settings);
sessionFactory = configuration.buildSessionFactory(serviceRegistry.build());
} catch (Exception e) {
e.printStackTrace();
}
}
return sessionFactory;
}
protected Properties getBuiltProperties(String propertyFileName) {
Properties properties = new Properties();
InputStream input = HibernateConfig.class
.getClassLoader().getResourceAsStream(propertyFileName);
try {
properties.load(input);
} catch (IOException e) {
e.printStackTrace();
}
return properties;
}

b) Session bean

@Bean(value = "session")
public Session getSession() {
try{
session = createAndGetLocalSessionFactoryBean().getCurrentSession();
} catch(HibernateException e) {
e.printStackTrace();
System.out.println("Opening new session...");
session = createAndGetLocalSessionFactoryBean().openSession();
}
return session;
}

The complete code for HibernateConfig class will look like below.

@org.springframework.context.annotation.Configuration
public class HibernateConfig {
private SessionFactory sessionFactory = null;

private Session session;

@Bean
public Session getSession() {
this.session = createAndGetLocalSessionFactoryBean().getCurrentSession();
return session != null
? this.session
: createAndGetLocalSessionFactoryBean().openSession();
}

@Bean
public SessionFactory createAndGetLocalSessionFactoryBean() {
if (this.sessionFactory == null) {
try {
Configuration configuration = new Configuration();
// Hibernate settings equivalent to hibernate.cfg.xml's properties
Properties settings = getBuiltProperties("hibernate.properties");

configuration.setProperties(settings);
configuration.addPackage("com.spring5.practice.model");
for (Class<?> clazz : (new Reflections("com.spring5.practice.model")).getTypesAnnotatedWith(Entity.class)) {
if (!Modifier.isAbstract(clazz.getModifiers())) {
configuration.addAnnotatedClass(clazz);
}
}
StandardServiceRegistryBuilder serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(settings);
sessionFactory = configuration.buildSessionFactory(serviceRegistry.build());
} catch (Exception e) {
e.printStackTrace();
}
}
return sessionFactory;
}

private Properties getBuiltProperties(String propertyFileName) {
Properties properties = new Properties();
InputStream input = HibernateConfig.class
.getClassLoader().getResourceAsStream(propertyFileName);
try {
properties.load(input);
} catch (IOException e) {
e.printStackTrace();
}
return properties;
}
}

Since, we can now get our session, our hibernate configuration can be considered as done potentially. However, if we want to minimize boilerplate codes, we can write a base Service class which will provide us the functionalities for Save, delete etc. The base class will look like below.

public abstract class BaseService<T> {

private SessionFactory sessionFactory = null;

private Session session;

private T model;

public BaseService(T model) {
this.model = model;
}

private Session getSession() {
try {
session = createAndGetLocalSessionFactoryBean().getCurrentSession();
} catch (HibernateException e) {
e.printStackTrace();
System.out.println("Opening new session...");
session = createAndGetLocalSessionFactoryBean().openSession();
}
return session;
}

private SessionFactory createAndGetLocalSessionFactoryBean() {
if (this.sessionFactory == null) {
try {
Configuration configuration = new Configuration();
// Hibernate settings equivalent to hibernate.cfg.xml's properties
Properties settings = getBuiltProperties("hibernate.properties");

configuration.setProperties(settings);
configuration.addPackage("com.spring5.practice.model");
configuration.addAnnotatedClass(model.getClass());
StandardServiceRegistryBuilder serviceRegistry = new StandardServiceRegistryBuilder()
.applySettings(settings);
sessionFactory = configuration.buildSessionFactory(serviceRegistry.build());
} catch (Exception e) {
e.printStackTrace();
}
}
return sessionFactory;
}

private Properties getBuiltProperties(String propertyFileName) {
Properties properties = new Properties();
InputStream input = HibernateConfig.class
.getClassLoader().getResourceAsStream(propertyFileName);
try {
properties.load(input);
} catch (IOException e) {
e.printStackTrace();
}
return properties;
}

protected Serializable save(T object) {
var session = getSession();
var tx = session.getTransaction();
if (!tx.isActive())
tx = session.beginTransaction();
var id = session.save(object);
session.flush();
tx.commit();
return id;
}

protected void delete(T object) {
var session = getSession();
var tx = session.getTransaction();
if (!tx.isActive())
tx = session.beginTransaction();
session.delete(object);
session.flush();
tx.commit();
}

protected CriteriaBuilder getCriteriaBuilder() {
Session session = getSession();
var tx = session.getTransaction();
if (!tx.isActive()) {
tx = session.beginTransaction();
}
return session.getCriteriaBuilder();
}

<T> TypedQuery<T> query(CriteriaQuery<T> query) {
return getSession().getEntityManagerFactory().createEntityManager().createQuery(query);
}
}

3. Service class

Now we will extend our base class in service class and use our newly created save, delete and query methods. The code is like below.

@Service
public class CourseService extends BaseService<Course>{

public CourseService() {
super(new Course());
}

public void addCourse(Course course) {
checkCourseInDb(course);
course.setCourseCode(course.getCourseName().substring(0, 2));
save(course);
}

private void checkCourseInDb(Course c) {

var cb = getCriteriaBuilder();
var cq = cb.createQuery(Course.class);
var root = cq.from(Course.class);

cq.where(cb.equal(root.get("courseCode"), c.getCourseCode()));
var result = query(cq).getResultList();
if(result.size() > 0){
throw new NonUniqueResultException(result.size());
}
}

public void saveEditedCourse(Course c) {
var cb = getCriteriaBuilder();
var cq = cb.createQuery(Course.class);
var root = cq.from(Course.class);

cq.where(cb.equal(root.get("courseId"), c.getCourseId()));
var result = query(cq).getResultList();
if (result.size() > 1) {
throw new NonUniqueResultException(result.size());
} else {
Course course = result.get(0);
BeanUtils.copyProperties(c, course);
save(course);
}
}

public Course getCourseByCourseCode(String courseCode) {

var cb = getCriteriaBuilder();
var cq = cb.createQuery(Course.class);
var root = cq.from(Course.class);

cq.where(cb.equal(root.get("courseCode"), courseCode));
var course = (Course)query(cq).getResultList().get(0);
return course;
}

public List<Course> getAllCourses() {

var cb = getCriteriaBuilder();
var cq = cb.createQuery(Course.class);
var root = cq.from(Course.class);
var result = query(cq).getResultList();
return result;
}
}

Now if we test our methods from UI, we will find it working. To get the code, click on this link.

--

--

Syed Hasan
Syed Hasan

Written by Syed Hasan

Software Engineer | Back-End Developer | Spring Developer | Cloud Enthusiast

Responses (1)