Build REST CRUD APIs with Spring Boot and MYSQL
Hello everyone, In this article, we will learn how to develop a REST-style web service with Spring Boot, Spring Data JPA, and MYSQL.The GitHub repository link is provided at the end of this tutorial. You could download the source code.
Technologies used :
- Spring Boot 2.6.3
- Spring Data JPA 2.6.3
- Java 11
- MYSQL connector
- MYSQL Server
- Maven 3+
These are APIs that Spring backend App will export:
Final Project Directory
Create database 'userdb'
CREATE DATABASE userdb;
Maven[pom.xml]
A Project Object Model or POM is the fundamental unit of work in Maven. It is an XML file that contains information about the project and configuration details utilized by Maven to build the project. It contains default values for most projects.
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.3</version> <relativePath/> </parent> <groupId>com.knf.dev.demo</groupId> <artifactId>spring-boot-mysql-rest-crud</artifactId> <version>0.0.1-SNAPSHOT</version> <name>spring-boot-mysql-rest-crud</name> <description>Demo project for Spring Boot</description> <properties> <java.version>11</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> </dependencies>
<build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin </artifactId> </plugin> </plugins> </build></project>
application.properties
We need to override the H2 database properties being set by default in Spring Boot. The following properties are needed to configure MySQL with Spring Boot. We can see these are pretty standard Java data source properties. Since in my example project, I’m using JPA too, we need to configure Hibernate for MySQL too.
**create-drop option tells Hibernate to recreate the database on startup
spring.datasource.url= jdbc:mysql://localhost:3306/userdbspring.datasource.username=rootspring.datasource.password=
spring.jpa.hibernate.ddl-auto=create-drop
server.port=8081
Creating the Entity User
The @Entity annotation specifies that the class is an entity and is mapped to a database table.
The @Id annotation specifies the primary key of an entity and the @GeneratedValue provides for the specification of generation strategies for the values of primary keys.
The @Column annotation is used to specify the mapped column for a persistent property or field. If no Column annotation is specified, the default value will be applied.
package com.knf.dev.demo.springbootmysqlrestcrud.entity;
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 = "user")public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @Column(name = "first_name") private String firstName; @Column(name = "last_name") private String lastName; @Column(name = "email", nullable = false, length = 200) private String email;
public User() { super(); }
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getFirstName() { return firstName; }
public void setFirstName(String firstName) { this.firstName = firstName; }
public String getLastName() { return lastName; }
public void setLastName(String lastName) { this.lastName = lastName; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public User(String firstName, String lastName, String email) { super(); this.firstName = firstName; this.lastName = lastName; this.email = email; }}
Creating the User Repository
CrudRepository is a Spring Data interface for generic CRUD operations on a repository of a specific type. It provides several methods out of the box for interacting with a database.
package com.knf.dev.demo.springbootmysqlrestcrud.repository;
import org.springframework.data.repository.CrudRepository;import com.knf.dev.demo.springbootmysqlrestcrud.entity.User;
public interface UserRepository extends CrudRepository<User, Long> {
}
Exception Handler with Controller Advice in Spring
Spring supports exception handling by a global Exception Handler (@ExceptionHandler) with Controller Advice (@ControllerAdvice). This enables a mechanism that makes ResponseEntity work with the type safety and flexibility of @ExceptionHandler:
package com.knf.dev.demo.springbootmysqlrestcrud.exception;
import java.util.Date;
import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.ControllerAdvice;import org.springframework.web.bind.annotation.ExceptionHandler;import org.springframework.web.context.request.WebRequest;
@ControllerAdvicepublic class GlobalExceptionHandler {
@ExceptionHandler(InternalServerError.class) public ResponseEntity<ErrorMessage> internalServerError(Exception ex, WebRequest request) { ErrorMessage errors = new ErrorMessage(500, new Date(), ex.getMessage(), "Internal Server Error");
return new ResponseEntity<> (errors, HttpStatus.INTERNAL_SERVER_ERROR); }
@ExceptionHandler(UserNotFound.class) public ResponseEntity<ErrorMessage> userNotFound(Exception ex, WebRequest request) { ErrorMessage errors = new ErrorMessage(404, new Date(), ex.getMessage(), "User Not Found");
return new ResponseEntity<> (errors, HttpStatus.NOT_FOUND); }}
Custom Exception - Internal Server Error
package com.knf.dev.demo.springbootmysqlrestcrud.exception;
public class InternalServerError extends RuntimeException { private static final long serialVersionUID = 1L;
public InternalServerError(String msg) { super(msg); }}
Custom Exception - UserNotFound
package com.knf.dev.demo.springbootmysqlrestcrud.exception;
public class UserNotFound extends RuntimeException { private static final long serialVersionUID = 1L;
public UserNotFound(String msg) { super(msg); }}
Error Message
package com.knf.dev.demo.springbootmysqlrestcrud.exception;
import java.util.Date;
public class ErrorMessage {
private Integer statusCode; private Date timestamp; private String message; private String description;
public Integer getStatusCode() { return statusCode; }
public void setStatusCode(Integer statusCode) { this.statusCode = statusCode; }
public Date getTimestamp() { return timestamp; }
public void setTimestamp(Date timestamp) { this.timestamp = timestamp; }
public String getMessage() { return message; }
public void setMessage(String message) { this.message = message; }
public String getDescription() { return description; }
public void setDescription(String description) { this.description = description; }
public ErrorMessage(Integer statusCode, Date timestamp, String message, String description) { super(); this.statusCode = statusCode; this.timestamp = timestamp; this.message = message; this.description = description; }}
User Rest Controller
The @RestController annotation was introduced in Spring 4.0 to simplify the engendering of RESTful web services. It's a convenience annotation that combines @Controller and @ResponseBody. @RequestMapping annotation maps HTTP requests to handler methods of MVC and REST controllers.
package com.knf.dev.demo.springbootmysqlrestcrud.controller;
import java.util.ArrayList;import java.util.List;import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.web.bind.annotation.DeleteMapping;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.PutMapping;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RestController;
import com.knf.dev.demo. springbootmysqlrestcrud.entity.User;import com.knf.dev.demo. springbootmysqlrestcrud.exception.InternalServerError;import com.knf.dev.demo. springbootmysqlrestcrud.exception.UserNotFound;import com.knf.dev.demo. springbootmysqlrestcrud.repository.UserRepository;
@RestController@RequestMapping("/api/v1/users")public class UserController {
@Autowired UserRepository userRepository;
// Create user @PostMapping public ResponseEntity<User> createUser(@RequestBody User user) { try { User newuser = new User(user.getFirstName(), user.getLastName(), user.getEmail()); userRepository.save(newuser); return new ResponseEntity<> (newuser, HttpStatus.CREATED); } catch (Exception e) { throw new InternalServerError(e.getMessage()); } }
// Update user @PutMapping("/{id}") public ResponseEntity<User> updateUser(@PathVariable("id") Long id, @RequestBody User user) {
Optional<User> userdata = userRepository.findById(id); if (userdata.isPresent()) { User _user = userdata.get(); _user.setEmail(user.getEmail()); _user.setFirstName(user.getFirstName()); _user.setLastName(user.getLastName()); return new ResponseEntity<> (userRepository.save(_user), HttpStatus.OK); } else { throw new UserNotFound("Invalid User Id"); } }
// Get all Users @GetMapping public ResponseEntity<List<User>> getAllUsers() {
try { List<User> users = new ArrayList<User>(); userRepository.findAll().forEach(users::add); return new ResponseEntity<>(users, HttpStatus.OK); } catch (Exception e) { throw new InternalServerError(e.getMessage()); }
}
// Get user by ID @GetMapping("/{id}") public ResponseEntity<User> getUserByID(@PathVariable("id") Long id) {
Optional<User> userdata = userRepository.findById(id); if (userdata.isPresent()) { return new ResponseEntity<> (userdata.get(), HttpStatus.OK); } else { throw new UserNotFound("Invalid User Id"); }
}
// Delete user @DeleteMapping("/{id}") public ResponseEntity<User> deleteUser(@PathVariable("id") Long id) {
Optional<User> userdata = userRepository.findById(id); if (userdata.isPresent()) { userRepository.deleteById(id); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } else { throw new UserNotFound("Invalid User Id"); } }}
Spring Boot main driver
package com.knf.dev.demo.springbootmysqlrestcrud;
import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplicationpublic class SpringBootMysqlRestCrudApplication {
public static void main(String[] args) { SpringApplication. run(SpringBootMysqlRestCrudApplication.class, args); }}
Download the complete source code - click here
Local Setup and Run the application
Step1: Download or clone the source code from GitHub to the local machine - Click here
Step 2: mvn clean install
Step 3: Run the Spring Boot application - mvn spring-boot:run
Step1: Download or clone the source code from GitHub to the local machine - Click here
Step 2: mvn clean install
Step 3: Run the Spring Boot application - mvn spring-boot:run
Testing APIs using Postman
Create user:
Update user:
Get all users:
Get user by id:
Delete a user by id: