Spring Boot MVC and Hibernate CRUD Example

Introduction

In this tutorial we will create an example on Spring Boot MVC and Hibernate CRUD. CRUD is an acronym that means Create, Read, Update and Delete operations. In my other tutorial I had also created Spring Boot MVC and JDBC CRUD Example.

We will build the tutorial example using both maven and gradle build tools. We will create the annotation based hibernate configuration with Spring Boot framework. We are going to use MySQL database as a persistence storage for our application.

Prerequisites

Eclipse 4.12, At least Java 8, Gradle 6.1.1, Maven 3.6.3, Spring Boot 2.2.4, Hibernate 5.4.11, MySQL 8.0.17

Create MySQL Table

First thing we recommend is to create a table called teacher in MySQL server under roytuts database.

CREATE TABLE `teacher` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  `expertise` varchar(50) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

As we are going to show some data initially when application URL is hit on the browser, so we are going to dump some data into the above table:

insert  into `teacher`(`id`,`name`,`expertise`)
values (16,'Bibhas Chandra Dhara','Statistics'),
(18,'UKR','System Programming'),
(19,'New','Expert');

Create Project

Now you may either create gradle or maven based project in the Eclipse IDE. The name of the project is spring-mvc-hibernate-crud.

If you are creating gradle based project then use below build.gradle script in order to build your project.

buildscript {
	ext {
		springBootVersion = '2.2.4.RELEASE'
	}
    repositories {
    	mavenLocal()
    	mavenCentral()
    }
    dependencies {
    	classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
    }
}

apply plugin: 'java'
apply plugin: 'org.springframework.boot'
    
sourceCompatibility = 12
targetCompatibility = 12

repositories {
	mavenLocal()
    mavenCentral()
}

dependencies {
	implementation("org.springframework.boot:spring-boot-starter-web:${springBootVersion}")
	implementation('org.springframework:spring-orm:5.2.3.RELEASE')
	implementation('org.apache.tomcat.embed:tomcat-embed-jasper:9.0.30')
    implementation('javax.servlet:jstl:1.2')
    implementation('org.hibernate:hibernate-core:5.4.11.Final')
    implementation('mysql:mysql-connector-java:8.0.17')
    //required only if jdk 9 or higher version is used
    runtimeOnly('javax.xml.bind:jaxb-api:2.4.0-b180830.0359')
}

If you are creating maven based project in Eclipse, then you may use the below pom.xml file for building your project.

<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.roytuts</groupId>
	<artifactId>spring-mvc-jdbc-crud</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.4.RELEASE</version>
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-orm</artifactId>
			<version>5.2.3.RELEASE</version>
		</dependency>
		
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-core</artifactId>
			<version>5.4.11.Final</version>
		</dependency>
		
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
			<version>9.0.30</version>
		</dependency>
		
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.2</version>
		</dependency>
		
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<version>8.0.17</version>
		</dependency>
		
		<!-- required only if jdk 9 or higher version is used -->
		<dependency>
			<groupId>javax.xml.bind</groupId>
			<artifactId>jaxb-api</artifactId>
			<version>2.4.0-b180830.0359</version>
		</dependency>
	</dependencies>

    <build>
        <plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<version>3.8.1</version>
				<configuration>
					<source>at least 8</source>
					<target>at least 8</target>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>

Database and View Resolver Configurations

Now we need to configure our database settings in Spring Boot application. We also need to configure view resolver as we are going to use JSP pages as view technology.

Create application.properties file under classpath directory src/main/resources with the following content.

#datasource
jdbc.driverClassName=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/roytuts
jdbc.username=root
jdbc.password=root

#view resolver
spring.mvc.view.prefix=/views/
spring.mvc.view.suffix=.jsp

Create corresponding DatasourceLocalSessionFactoryBean and HibernateTransactionManager beans to interact with database and perform the required CRUD operations.

package com.roytuts.spring.mvc.hibernate.crud.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.hibernate5.HibernateTransactionManager;
import org.springframework.orm.hibernate5.LocalSessionFactoryBean;

@Configuration
public class DbConfig {

	@Autowired
	private Environment environment;

	@Bean
	public DataSource dataSource() {
		DriverManagerDataSource dataSource = new DriverManagerDataSource();

		dataSource.setDriverClassName(environment.getProperty("jdbc.driverClassName"));
		dataSource.setUrl(environment.getProperty("jdbc.url"));
		dataSource.setUsername(environment.getProperty("jdbc.username"));
		dataSource.setPassword(environment.getProperty("jdbc.password"));

		return dataSource;
	}

	@Bean
	public LocalSessionFactoryBean getSessionFactory() {
		LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean();
		factoryBean.setDataSource(dataSource());

		Properties props = new Properties();
		props.put("format_sql", "true");
		props.put("hibernate.show_sql", "true");

		factoryBean.setHibernateProperties(props);
		factoryBean.setPackagesToScan("com.roytuts.spring.mvc.hibernate.crud.entity");
		// factoryBean.setAnnotatedClasses(Teacher.class);
		return factoryBean;
	}

	@Bean
	public HibernateTransactionManager getTransactionManager() {
		HibernateTransactionManager transactionManager = new HibernateTransactionManager();
		transactionManager.setSessionFactory(getSessionFactory().getObject());
		return transactionManager;
	}

}

Entity Class

We need a Java POJO class that will simply represent database table.

We have specified the table name above the class to indicate which table to map with the following Java class. As we have the same Java attribute names and table column names so we have not specified the column name using @Column annotation on the Java attributes otherwise you have specify.

package com.roytuts.spring.mvc.hibernate.crud.entity;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "teacher")
public class Teacher implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
        @Column
	private int id;

	@Column
	private String name;

	@Column
	private String expertise;

	public Teacher() {
	}

	public Teacher(int id, String name, String expertise) {
		this.id = id;
		this.name = name;
		this.expertise = expertise;
	}

	//getters and setters

}

Repository Class

The repository is sole responsible for fetching data, updating data, inserting data and deleting data into database table.

We have applied Spring’s transaction to rollback the any write to database in case any exception occurs. Generally Transactional annotation should be used for write operations only (on methods) but for simplicity I have put it on class level.

package com.roytuts.spring.mvc.hibernate.crud.repository;

import java.util.List;

import javax.persistence.TypedQuery;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.roytuts.spring.mvc.hibernate.crud.entity.Teacher;

@Repository
@Transactional
public class TeacherDao {

	@Autowired
	private SessionFactory sessionFactory;

	public Teacher getTeacher(final int id) {
		@SuppressWarnings("unchecked")
		TypedQuery<Teacher> q = sessionFactory.getCurrentSession().createQuery("from Teacher t where t.id = :id")
				.setParameter("id", id);

		return q.getSingleResult();
	}

	public List<Teacher> getTeachers() {
		@SuppressWarnings("unchecked")
		TypedQuery<Teacher> q = sessionFactory.getCurrentSession().createQuery("from Teacher");

		return q.getResultList();
	}

	public void addTeacher(final Teacher teacher) {
		sessionFactory.getCurrentSession().save(teacher);
	}

	public void updateTeacher(final Teacher teacher) {
		sessionFactory.getCurrentSession().saveOrUpdate(teacher);
	}

	public void deleteTeacher(final int id) {
		sessionFactory.getCurrentSession().createQuery("delete from Teacher t where t.id = :id").setParameter("id", id)
				.executeUpdate();
	}

}

Service Class

Any business operation is performed in the service class.

package com.roytuts.spring.mvc.hibernate.crud.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.roytuts.spring.mvc.hibernate.crud.entity.Teacher;
import com.roytuts.spring.mvc.hibernate.crud.repository.TeacherDao;

@Service
public class TeacherService {

	@Autowired
	private TeacherDao teacherDao;

	public Teacher getTeacher(final int id) {
		return teacherDao.getTeacher(id);
	}

	public List<Teacher> getTeachers() {
		return teacherDao.getTeachers();
	}

	public void addTeacher(final Teacher teacher) {
		teacherDao.addTeacher(teacher);
	}

	public void updateTeacher(final Teacher teacher) {
		teacherDao.updateTeacher(teacher);
	}

	public void deleteTeacher(final int id) {
		teacherDao.deleteTeacher(id);
	}

}

Controller Class

Create Spring controller class which will handle user request and response. This class exposes the endpoint through which client sends or receives the required data.

package com.roytuts.spring.mvc.hibernate.crud.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;

import com.roytuts.spring.mvc.hibernate.crud.entity.Teacher;
import com.roytuts.spring.mvc.hibernate.crud.service.TeacherService;

@Controller
public class TeacherController {

	@Autowired
	private TeacherService teacherService;

	@GetMapping("/teacher/{id}")
	public String getTeacher(@PathVariable int id, ModelMap teacherModel) {
		Teacher teacher = teacherService.getTeacher(id);
		teacherModel.addAttribute("teacher", teacher);
		return "teacher";
	}

	@GetMapping("/teachers")
	public String getTeachers(ModelMap teacherModel) {
		List<Teacher> teachers = teacherService.getTeachers();
		teacherModel.addAttribute("teachers", teachers);
		return "teachers";
	}

	@GetMapping("addTeacher")
	public String addPage() {
		return "add";
	}

	@PostMapping("/add/teacher")
	public String addTeacher(@RequestParam(value = "name", required = true) String name,
			@RequestParam(value = "expertise", required = true) String expertise, ModelMap teacherModel) {
		Teacher teacher = new Teacher();
		teacher.setName(name);
		teacher.setExpertise(expertise);
		teacherService.addTeacher(teacher);
		teacherModel.addAttribute("msg", "Teacher added successfully");
		List<Teacher> teachers = teacherService.getTeachers();
		teacherModel.addAttribute("teachers", teachers);
		return "redirect:/teachers";
	}

	@GetMapping("update/teacher/{id}")
	public String updatePage(@PathVariable("id") int id, ModelMap teacherModel) {
		teacherModel.addAttribute("id", id);
		Teacher teacher = teacherService.getTeacher(id);
		teacherModel.addAttribute("teacher", teacher);
		return "update";
	}

	@PostMapping("/update/teacher")
	public String updateTeacher(@RequestParam int id, @RequestParam(value = "name", required = true) String name,
			@RequestParam(value = "expertise", required = true) String expertise, ModelMap teacherModel) {
		Teacher teacher = new Teacher(id,name,expertise);
		/*
		 * teacher.setId(id); teacher.setName(name); teacher.setExpertise(expertise);
		 */
		teacherService.updateTeacher(teacher);
		List<Teacher> teachers = teacherService.getTeachers();
		teacherModel.addAttribute("teachers", teachers);
		teacherModel.addAttribute("id", id);
		teacherModel.addAttribute("msg", "Teacher updated successfully");
		return "redirect:/teachers";
	}

	@GetMapping("/delete/teacher/{id}")
	public String deleteTeacher(@PathVariable int id, ModelMap teacherModel) {
		teacherService.deleteTeacher(id);
		List<Teacher> teachers = teacherService.getTeachers();
		teacherModel.addAttribute("teachers", teachers);
		teacherModel.addAttribute("msg", "Teacher delted successfully");
		return "redirect:/teachers";
	}

}

Create Main Class

A class with main method and @SpringBootApplication is enough to deploy the Spring Boot application into embedded Tomcat server.

package com.roytuts.spring.mvc.hibernate.crud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;

@SpringBootApplication(exclude = HibernateJpaAutoConfiguration.class)
public class SpringMvcHibernateCrudApp {

	public static void main(String[] args) {
		SpringApplication.run(SpringMvcHibernateCrudApp.class, args);
	}

}

Web Pages

As this application is Spring Boot MVC, so we will create few web pages to perform our CRUD (Create Read Update Delete) operations.

We will put web pages (JSP) under src/main/webapp/views directory.

teachers.jsp

This page will show all teachers from database. This page has a link called Add that will give you the page for adding new record.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<title>Spring Boot MVC and Hibernate CRUD Example</title>
<body>
	<h2>Spring Boot MVC and Hibernate CRUD Example</h2>
	<a href="<%=request.getContextPath()%>/addTeacher">Add</a>
	<c:if test="${not empty msg}">
        ${msg}
    </c:if>
	<c:choose>
		<c:when test="${teachers != null}">
			<h3>List of Teachers</h3>
			<table cellpadding="5" cellspacing="5">
				<thead>
					<tr>
						<th>ID</th>
						<th>Name</th>
						<th>Expertise</th>
						<th>Actions</th>
					</tr>
				</thead>
				<tbody>
					<c:forEach var="t" items="${teachers}">
						<tr>
							<td>${t.id}</td>
							<td>${t.name}</td>
							<td>${t.expertise}</td>
							<td><a
								href="<%=request.getContextPath()%>/teacher/${t.id}">Details</a>
								&nbsp;<a
								href="<%=request.getContextPath()%>/update/teacher/${t.id}">Update</a>
								&nbsp; <a
								href="<%=request.getContextPath()%>/delete/teacher/${t.id}"
								onclick="return confirm('Do you really want to delete?')">Delete</a></td>
						</tr>
					</c:forEach>
				</tbody>
			</table>
		</c:when>
		<c:otherwise>
        No User found in the DB!
        </c:otherwise>
	</c:choose>
</body>
</html>

teacher.jsp

This page shows details of a particular teacher when you click on link Details.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<html>
<title>Spring Boot MVC and Hibernate CRUD Example</title>
<body>
	<h2>Spring Boot MVC and Hibernate CRUD Example</h2>
	Id : ${teacher.id}
	<br /> Name : ${teacher.name}
	<br /> Expertise : ${teacher.expertise}
</body>
</html>

add.jsp

This page has the input fields which will be used to add new records.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<title>Spring Boot MVC and Hibernate CRUD Example</title>
<body>
	<h2>Spring Boot MVC and Hibernate CRUD Example</h2>
	<c:if test="${not empty msg}">
        ${msg}
    </c:if>
	<h3>Add User</h3>
	<form method="POST" name="add_teacher"
		action="<%=request.getContextPath()%>/add/teacher">
		Name: <input name="name" value="${name}" type="text" /> <br /> <br />
		Expertise: <input name="expertise" value="${expertise}" type="text" />
		<br /> <br />
		<input value="Add Teacher" type="submit" />
	</form>
</body>
</html>

update.jsp

This page is responsible fir updating the existing records. The input fields on this page will be populated with the existing records in edit mode.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
	pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<html>
<title>Spring Boot MVC and Hibernate CRUD Example</title>
<body>
	<h2>Spring Boot MVC and Hibernate CRUD Example</h2>
	<c:if test="${not empty msg}">
        ${msg}
    </c:if>
	<h3>Update User</h3>
	<form method="POST" name="update_teacher"
		action="<%=request.getContextPath()%>/update/teacher">
		<input hidden="hidden" name="id" value="${id}" type="text" /> Name: <input
			name="name" value="${teacher.name}" type="text" /> <br /> <br />
		Expertise: <input name="expertise" value="${teacher.expertise}"
			type="text" /> <br /> <br /> <input value="Update User"
			type="submit" />
	</form>
</body>
</html>

Testing the Application

Once you execute the class having main method and hit the URL http://localhost:8080/teachers on the browser you will see the following page:

spring boot mvc and hibernate crud example

Let’s say you want to read or see single teacher details then you can hit URL, for example, http://localhost:8080/teacher/16, where 16 is the id of the teacher or you can click on the Details link.

spring boot mvc and hibernate crud example

Let’s say we want to add new record as shown below. Click on the Add link on list of teachers page.

spring boot mvc and hibernate crud example

You will be redirected to the list of teachers page with new record added.

spring boot mvc and hibernate crud example

Let’s say now we want to update the last record that has name “New” with the following records:

spring boot mvc and hibernate crud example

Once updated successfully you will be redirected to the list of teachers page and you will see your record has been updated.

Let’s say we want to delete record. So we want to delete the new record we just added/updated.

You will get a confirm box whether you really want to delete the record.

spring boot mvc and hibernate crud example

So your record will be deleted and you will be redirected to the list of teachers page.

Source Code

Download

Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *