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.
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.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
- Enter the content as shown below
- Click Next
- Spring Boot Version is 2.1.0 (SNAPSHOT)
- JPA
- Web
- MySQL
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.
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 contentspackage 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 contentspackage 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 contentspackage 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.
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
Add New Article
Type the following URLs in browser's address bar to open the Add New Article page.
http://localhost:8080/article/addArticle/
Update Article
Type the following URLs in browser's address bar to open the Update Article page.
http://localhost:8080/article/updateArticle/1