Build REST CRUD APIs with Spring Boot and MyBatis

Hello every one, here we will learn how to develop REST-style CRUD APIs with Spring Boot, MyBatis, and H2 Database with Annotation mapping. You can download the source code from our Github repository.


After completing this tutorial what we will build? 

We will build REST API  CRUD features: 
  1. GET - Fetch all User       :     /api/v1/users
  2. GET - Get User by ID     :     /api/v1/users/{id} 
  3. POST - Create User         :     /api/v1/users 
  4. PUT - Edit User Details   :     /api/v1/users/{id} 
  5. DELETE - Delete User    :     /api/v1/users/{id}

Project Directory:


Maven dependencies(pom.xml)

Puts mybatis-spring-boot-starter, h2 dependencies.
<?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.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>springboot-mybatis-crud-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-mybatis-crud-example</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-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</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>

Database Setup

We will create a table called users with a few simple columns. 
We can initialize a schema by creating a schema.sql file in the resources.
create table users
(
id integer not null,
firstName varchar(255) not null,
lastName varchar(255) not null,
emailId varchar(255) not null,
primary key(id)
);

Create User Model 

package com.knf.dev.demo.springbootmybatiscrudexample.model;

public class User {

private long id;
private String firstName;
private String lastName;
private String emailId;

public User() {
}

public User(long id,String firstName,
              String lastName, String emailId) {
super();
this.id=id;
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
}

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 getEmailId() {
return emailId;
}

public void setEmailId(String emailId) {
this.emailId = emailId;
}
}

Create User MyBatis Repository 

The MyBatis-Spring-Boot-Starter will search, by default, for mappers marked with the @Mapper annotation. In this example, we are not using XML mappings.
package com.knf.dev.demo.springbootmybatiscrudexample.repository;

import com.knf.dev.demo.springbootmybatiscrudexample.model.User;
import org.apache.ibatis.annotations.*;
import java.util.List;

@Mapper
public interface UserRepository {

@Select("select * from users")
public List<User> findAll();

@Select("SELECT * FROM users WHERE id = #{id}")
public User findById(long id);

@Delete("DELETE FROM users WHERE id = #{id}")
public int deleteById(long id);

@Insert("INSERT INTO users(id, firstName, lastName,emailId) " +
" VALUES (#{id}, #{firstName}, #{lastName}, #{emailId})")
public int insert(User user);

@Update("Update users set firstName=#{firstName}, " +
" lastName=#{lastName}, emailId=#{emailId} where id=#{id}")
public int update(User user);
}

Create User Rest Controller

package com.knf.dev.demo.springbootmybatiscrudexample.controller;

import com.knf.dev.demo.springbootmybatiscrudexample.
                           exception.UserIdAlreadyExistException;
import com.knf.dev.demo.springbootmybatiscrudexample.
                           exception.UserIdNotFoundException;
import com.knf.dev.demo.springbootmybatiscrudexample.model.User;
import com.knf.dev.demo.springbootmybatiscrudexample.
                           repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api/v1/")
public class UserController {
@Autowired
private UserRepository userRepository;

// get all users
@GetMapping("/users")
public List<User> getAllUsers()
{
return userRepository.findAll();
}

// create user rest API
@PostMapping("/users")
public User createUser(@RequestBody User user) {
if(userRepository.findById(user.getId())==null) {
int id = userRepository.insert(user);
return userRepository.findById(user.getId());
}else
{
throw new UserIdAlreadyExistException();
}

}

// get user by id rest api
@GetMapping("/users/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userRepository.findById(id);
if(user==null)
{
throw new UserIdNotFoundException();
}
return ResponseEntity.ok(user);
}

// update user rest api
@PutMapping("/users/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id,
@RequestBody User userDetails) {
if(userRepository.update(new User(id, userDetails.getFirstName(),
         userDetails.getLastName(), userDetails.getEmailId()))==0)
{
throw new UserIdNotFoundException();
}

return ResponseEntity.ok(userRepository.findById(id));
}

// delete user rest api
@DeleteMapping("/users/{id}")
public ResponseEntity<Map<String, Boolean>> deleteUser
(@PathVariable Long id) {
userRepository.deleteById(id);
Map<String, Boolean> response = new HashMap<>();
response.put("deleted", Boolean.TRUE);
return ResponseEntity.ok(response);
}
}

Create Custom Exception

UserIdNotFoundException

package com.knf.dev.demo.springbootmybatiscrudexample.exception;

public class UserIdNotFoundException extends RuntimeException{
public UserIdNotFoundException()
{
super("User Id Not Found");
}
}

UserIdAlreadyExistException

package com.knf.dev.demo.springbootmybatiscrudexample.exception;

public class UserIdAlreadyExistException extends RuntimeException{
public UserIdAlreadyExistException() {
super("User Id Already Exist");
}
}

GlobalExceptionHandler

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.springbootmybatiscrudexample.exception;

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;
import java.time.LocalDateTime;

@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(UserIdNotFoundException.class)
public ResponseEntity<CustomErrorResponse>
        globalExceptionHandler(Exception ex, WebRequest request) {
CustomErrorResponse errors = new CustomErrorResponse();
errors.setTimestamp(LocalDateTime.now());
errors.setError(ex.getMessage());
errors.setStatus(HttpStatus.NOT_FOUND.value());
return new ResponseEntity<>(errors, HttpStatus.NOT_FOUND);
}

@ExceptionHandler(UserIdAlreadyExistException.class)
public ResponseEntity<CustomErrorResponse>
        globalExceptionHandler2(Exception ex, WebRequest request) {

CustomErrorResponse errors = new CustomErrorResponse();
errors.setTimestamp(LocalDateTime.now());
errors.setError(ex.getMessage());
errors.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
return new ResponseEntity<>
                 (errors, HttpStatus.INTERNAL_SERVER_ERROR);
}
}

CustomErrorResponse

package com.knf.dev.demo.springbootmybatiscrudexample.exception;

import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;

public class CustomErrorResponse {

@JsonFormat(shape = JsonFormat.Shape.STRING,
                       pattern = "yyyy-MM-dd hh:mm:ss")
private LocalDateTime timestamp;
private int status;
private String error;
public LocalDateTime getTimestamp()
{
return timestamp;
}
public void setTimestamp(LocalDateTime timestamp)
{
this.timestamp = timestamp;
}
public int getStatus()
{
return status;
}
public void setStatus(int status)
{
this.status = status;
}
public String getError()
{
return error;
}
public void setError(String error)
{
this.error = error;
}
}

Spring Boot Main Class

package com.knf.dev.demo.springbootmybatiscrudexample;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootMybatisCrudExampleApplication {

public static void main(String[] args) {
SpringApplication.
         run(SpringbootMybatisCrudExampleApplication.class, args);
}
}
The Spring Boot application's main class contains a public static void main() method that starts up the Spring ApplicationContext.

Local Setup

Step 1: Download or clone the source code to a local machine.

Step 2mvn clean install

Step 3: Run the Spring Boot application
mvn spring-boot:run

Testing API's using Postman

Create a User:

Fetch all User:

Get User by ID:

Update User:

Delete User by ID:

More related topics,

Popular posts from this blog

Spring boot video streaming example-HTML5

Learn Java 8 streams with an example - print odd/even numbers from Array and List

Spring Boot + Mockito simple application with 100% code coverage

Spring Boot + OpenCSV Export Data to CSV Example

Custom Exception Handling in Quarkus REST API

DataTable-Pagination example with Spring boot, jQuery and ajax

Registration and Login with Spring Boot + Spring Security + Thymeleaf

Node JS mini projects with source code - free download

Spring boot web project free download:User Registration System

Java - Blowfish Encryption and decryption Example