Overview

In this tutorial, we show you how to develop a Web application CRUD example using Spring Boot 2.1.0, Spring MVC, Spring JPA, Hibernate and MySQL as database. We will add the dependencies for Bootstrap 4.0.0 and jQuery 3.0.0 Web jars. We use Spring Tool Suite to create Spring Boot Maven Project for this tutorials.
Follow the steps mentioned below to develop the Web Application.

Spring data JPA CRUD Example

Watch Tutorial

Following Technologies Used

  • Eclipse IDE and Spring Tool Suite plugin for Eclipse
  • Spring Boot 2.1.0.BUILD-SNAPSHOT
  • spring-boot-starter-data-jpa
  • spring-boot-starter-web
  • mysql-connector-java
  • JSTL - JSP Standard Tag Library
  • tomcat-embed-jasper
  • Bootstrap 4.0.0 Webjars
  • Java 8+

Creating database and tables in MySQL

CREATE DATABASE `jackrutorial` /*!40100 DEFAULT CHARACTER SET utf8 */;

DROP TABLE IF EXISTS `jackrutorial`.`article`;
CREATE TABLE  `jackrutorial`.`article` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `title` varchar(100) NOT NULL default '',
  `category` varchar(100) NOT NULL default '',
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

Project Structure

Review the following screenshot shows structure of the project.
Spring data JPA CRUD Example Project Structure

Steps to Create Simple Maven Project in Eclipse

  • Launch Eclipse IDE.
  • Go to File -> New -> Other...
  • Select Spring Starter Project under Spring Boot category
  • Click Next as shown below
Create Simple Maven Project in Eclipse
  • Enter the content as shown below
  • Click Next
Spring-data-JPA-CRUD-Example-Steps
In the next step, we selected:
  • Spring Boot Version is 2.1.0 (SNAPSHOT)
  • JPA
  • Web
  • MySQL
Spring-data-JPA-CRUD-Example-Steps-final

Project Dependencies

We will add the required dependencies to Maven pom.xml file
<dependency>
 <groupId>javax.servlet</groupId>
 <artifactId>jstl</artifactId>
</dependency>
<dependency>
 <groupId>org.apache.tomcat.embed</groupId>
 <artifactId>tomcat-embed-jasper</artifactId>
 <scope>provided</scope>
</dependency>
<dependency>
 <groupId>org.webjars</groupId>
 <artifactId>bootstrap</artifactId>
 <version>4.0.0</version>
</dependency>
The pom.xml file will have the following code
<?xml version="1.0" encoding="UTF-8"?>
<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.jackrutorial</groupId>
 <artifactId>SpringBootSpringJPACRUDExample</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>jar</packaging>

 <name>SpringBootSpringJPACRUDExample</name>
 <description>Demo project for Spring Boot</description>

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.1.0.BUILD-SNAPSHOT</version>
  <relativePath /> <!-- lookup parent from repository -->
 </parent>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
  <java.version>1.8</java.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-jpa</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>

  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <scope>runtime</scope>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
  </dependency>
  <dependency>
   <groupId>org.apache.tomcat.embed</groupId>
   <artifactId>tomcat-embed-jasper</artifactId>
   <scope>provided</scope>
  </dependency>
  <dependency>
   <groupId>org.webjars</groupId>
   <artifactId>bootstrap</artifactId>
   <version>4.0.0</version>
  </dependency>
 </dependencies>

 <build>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
  </plugins>
 </build>

 <repositories>
  <repository>
   <id>spring-snapshots</id>
   <name>Spring Snapshots</name>
   <url>https://repo.spring.io/snapshot</url>
   <snapshots>
    <enabled>true</enabled>
   </snapshots>
  </repository>
  <repository>
   <id>spring-milestones</id>
   <name>Spring Milestones</name>
   <url>https://repo.spring.io/milestone</url>
   <snapshots>
    <enabled>false</enabled>
   </snapshots>
  </repository>
 </repositories>

 <pluginRepositories>
  <pluginRepository>
   <id>spring-snapshots</id>
   <name>Spring Snapshots</name>
   <url>https://repo.spring.io/snapshot</url>
   <snapshots>
    <enabled>true</enabled>
   </snapshots>
  </pluginRepository>
  <pluginRepository>
   <id>spring-milestones</id>
   <name>Spring Milestones</name>
   <url>https://repo.spring.io/milestone</url>
   <snapshots>
    <enabled>false</enabled>
   </snapshots>
  </pluginRepository>
 </pluginRepositories>


</project>

Entity

Let’s now create the Article entity. Our Article entity has following fields
  • id: Primary Key with Auto Increment.
  • title: The title of the Article.
  • category: The category of the Article.
Create a new package called model inside com.jackrutorial.model and add a class named Article.java with following contents
package com.jackrutorial.model;

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="article")
public class Article {

 @Id
 @GeneratedValue(strategy = GenerationType.IDENTITY)
 private long id;
 
 @Column(name="title")
 private String title;
 
 @Column(name="category")
 private String category;

 public long getId() {
  return id;
 }

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

 public String getTitle() {
  return title;
 }

 public void setTitle(String title) {
  this.title = title;
 }

 public String getCategory() {
  return category;
 }

 public void setCategory(String category) {
  this.category = category;
 }
}

Creating ArticleRepository to access data from the database

Create a new package called repository inside com.jackrutorial.repository and add a interface named ArticleRepository.java with following contents
package com.jackrutorial.repository;

import org.springframework.data.repository.CrudRepository;

import com.jackrutorial.model.Article;

public interface ArticleRepository extends CrudRepository<Article, Long> {

}

Service Layer

Create a new package called service inside com.jackrutorial.service and add a interface named ArticleService.java with following contents
package com.jackrutorial.service;

import java.util.List;

import com.jackrutorial.model.*;

public interface ArticleService {

 public List<Article> getAllArticles();
 
 public Article getArticleById(long id);
 
 public void saveOrUpdate(Article article);
 
 public void deleteArticle(long id);
}
Create a ArticleServiceImpl class implements ArticleService interface under com.jackrutorial.service package with the following contents.
package com.jackrutorial.service;

import java.util.List;

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

import com.jackrutorial.model.Article;
import com.jackrutorial.repository.ArticleRepository;

@Service
@Transactional
public class ArticleServiceImpl implements ArticleService {
 
 @Autowired
 ArticleRepository articleRepository;

 @Override
 public List<Article> getAllArticles() {
  return (List<Article>) articleRepository.findAll();
 }

 @Override
 public Article getArticleById(long id) {
  return articleRepository.findById(id).get();
 }

 @Override
 public void saveOrUpdate(Article article) {
  articleRepository.save(article);
 }

 @Override
 public void deleteArticle(long id) {
  articleRepository.deleteById(id);
 }

}

Creating Controller

Create a new package called controller inside com.jackrutorial.controller and add a class named ArticleController.java with following contents
package com.jackrutorial.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.jackrutorial.model.Article;
import com.jackrutorial.service.ArticleService;

@Controller
@RequestMapping(value="/article")
public class ArticleController {

 @Autowired
 ArticleService articleService;
 
 @RequestMapping(value="/list", method=RequestMethod.GET)
 public ModelAndView list() {
  ModelAndView model = new ModelAndView("article_list");
  List<Article> articleList = articleService.getAllArticles();
  model.addObject("articleList", articleList);
  
  return model;
 }
 
 @RequestMapping(value="/addArticle/", method=RequestMethod.GET)
 public ModelAndView addArticle() {
  ModelAndView model = new ModelAndView();
  
  Article article = new Article();
  model.addObject("articleForm", article);
  model.setViewName("article_form");
  
  return model;
 }
 
 @RequestMapping(value="/updateArticle/{id}", method=RequestMethod.GET)
 public ModelAndView editArticle(@PathVariable long id) {
  ModelAndView model = new ModelAndView();
  
  Article article = articleService.getArticleById(id);
  model.addObject("articleForm", article);
  model.setViewName("article_form");
  
  return model;
 }
 
 @RequestMapping(value="/saveArticle", method=RequestMethod.POST)
 public ModelAndView save(@ModelAttribute("articleForm") Article article) {
  articleService.saveOrUpdate(article);
  
  return new ModelAndView("redirect:/article/list");
 }
 
 @RequestMapping(value="/deleteArticle/{id}", method=RequestMethod.GET)
 public ModelAndView delete(@PathVariable("id") long id) {
  articleService.deleteArticle(id);
  
  return new ModelAndView("redirect:/article/list");
 }
}

Configuring MySQL Database, Spring Data JPA and View Resolvers

Open application.properties file and add the following properties to it.
#database
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/jackrutorial
spring.datasource.username=root
spring.datasource.password=root

#spring jpa
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL5Dialect

spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

View Layer

Create jsp folder under src\main\webapp\WEB-INF\ folder. We will include the tags library into our JSP page. The spring taglib, form taglib and JSTL taglib.
Create article_list.jsp and article_form.jsp file under src\main\webapp\WEB-INF\jsp\ folder and write the following code in it.
article_list.jsp
<%@ 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"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>   
    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title>Article List</title>
 <link href="../../webjars/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
 <script src="../../webjars/bootstrap/4.0.0/js/bootstrap.min.js"></script>
 <script src="../../webjars/jquery/3.0.0/js/jquery.min.js"></script>
</head>
<body>
 <div class="container">
  <h2>Article List</h2>
  <table class="table table-striped">
   <thead>
    <th scope="row">#ID</th>
    <th scope="row">Title</th>
    <th scope="row">Category</th>
    <th scope="row">Update</th>
    <th scope="row">Delete</th>
   </thead>
   <tbody>
    <c:forEach items="${articleList }" var="article" >
     <tr>
      <td>${article.id }</td>
      <td>${article.title }</td>
      <td>${article.category }</td>
      <td>
       <spring:url value="/article/updateArticle/${article.id }" var="updateURL" />
       <a class="btn btn-primary" href="${updateURL }" role="button" >Update</a>
      </td>
      <td>
       <spring:url value="/article/deleteArticle/${article.id }" var="deleteURL" />
       <a class="btn btn-primary" href="${deleteURL }" role="button" >Delete</a>
      </td>
     </tr>
    </c:forEach>
   </tbody>
  </table>
  <spring:url value="/article/addArticle/" var="addURL" />
  <a class="btn btn-primary" href="${addURL }" role="button" >Add New Article</a>
 </div>
</body>
</html>
article_form.jsp
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%> 
<%@ taglib uri="http://www.springframework.org/tags/form" prefix="form"%>     
    
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title>Article Form</title>
 <link href="../../webjars/bootstrap/4.0.0/css/bootstrap.min.css" rel="stylesheet" />
 <script src="../../webjars/bootstrap/4.0.0/js/bootstrap.min.js"></script>
 <script src="../../webjars/jquery/3.0.0/js/jquery.min.js"></script>
</head>
<body>
 <div class="container">
  <spring:url value="/article/saveArticle" var="saveURL" />
  <h2>Article</h2>
  <form:form modelAttribute="articleForm" method="post" action="${saveURL }" cssClass="form" >
   <form:hidden path="id"/>
   <div class="form-group">
    <label>Title</label>
    <form:input path="title" cssClass="form-control" id="title" />
   </div>
   <div class="form-group">
    <label>Category</label>
    <form:input path="category" cssClass="form-control" id="category" />
   </div>
   <button type="submit" class="btn btn-primary">Save</button>
  </form:form>
  
 </div>
</body>
</html>

Buid and Run Web Application

Right click to the Project and follow the below steps:
  • select Run As -> Maven clean.
  • select Run As -> Maven install.
  • select Run As -> Spring Boot App.
View console output in eclipse, you will see following output
INFO 12384 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/article/deleteArticle/{id}],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView com.jackrutorial.controller.ArticleController.delete(long)
INFO 12384 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/article/list],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView com.jackrutorial.controller.ArticleController.list()
INFO 12384 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/article/saveArticle],methods=[POST]}" onto public org.springframework.web.servlet.ModelAndView com.jackrutorial.controller.ArticleController.save(com.jackrutorial.model.Article)
INFO 12384 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/article/addArticle/],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView com.jackrutorial.controller.ArticleController.addArticle()
INFO 12384 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/article/updateArticle/{id}],methods=[GET]}" onto public org.springframework.web.servlet.ModelAndView com.jackrutorial.controller.ArticleController.editArticle(long)
INFO 12384 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error]}" onto public org.springframework.http.ResponseEntity<java.util.Map<java.lang.String, java.lang.Object>> org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.error(javax.servlet.http.HttpServletRequest)
INFO 12384 --- [           main] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped "{[/error],produces=[text/html]}" onto public org.springframework.web.servlet.ModelAndView org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController.errorHtml(javax.servlet.http.HttpServletRequest,javax.servlet.http.HttpServletResponse)
INFO 12384 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/webjars/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
INFO 12384 --- [           main] o.s.w.s.handler.SimpleUrlHandlerMapping  : Mapped URL path [/**] onto handler of type [class org.springframework.web.servlet.resource.ResourceHttpRequestHandler]
INFO 12384 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
INFO 12384 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Bean with name 'dataSource' has been autodetected for JMX exposure
INFO 12384 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Located MBean 'dataSource': registering with JMX server as MBean [com.zaxxer.hikari:name=dataSource,type=HikariDataSource]
INFO 12384 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
INFO 12384 --- [           main] c.j.SpringBootSpringJpacrudApplication   : Started SpringBootSpringJpacrudApplication in 3.992 seconds (JVM running for 4.838)
View Article List
Type the following URLs in browser's address bar to open the Article List page.
http://localhost:8080/article/list
Article-List-Screen

Add New Article
Type the following URLs in browser's address bar to open the Add New Article page.
http://localhost:8080/article/addArticle/
Article-Add-Screen

Update Article
Type the following URLs in browser's address bar to open the Update Article page.
http://localhost:8080/article/updateArticle/1
Article-Update-Screen

Previous Post
Next Post

post written by: