Build REST CRUD APIs with Spring Boot, MyBatis(Using Annotations), & PostgreSQL
In this section, we will learn how to develop a REST-style web service with Spring Boot, MyBatis(Using Annotations) and PostgreSQL. GitHub repository link is provided at the end of this tutorial. You can download the source code.
Technologies used:
- Spring Boot 3.0.1
- MyBatis 3
- Java 17
- Maven
- PostgreSQL driver and database
These are APIs that Spring Boot backend App will export:
Creating a simple spring boot web application:
First, open the Spring initializr https://start.spring.io/
Then, Provide the Group and Artifact name. We have provided Group name com.knf.dev.demo and Artifact spring-boot-postgresql-mybatis-crud. Here I selected the Maven project - language Java 17 - Spring Boot 3.0.1 and add Spring web dependency, MyBatis Framework and PostgreSQL Driver.
Then, click on the Generate button. When we click on the Generate button, it starts packing the project in a .zip(spring-boot-postgresql-mybatis-crud) file and downloads the project. Then, Extract the Zip file.
Then, import the project on your favourite IDE.
Final Project directory:
Create database.
First, you need to create a database in the PostgreSQL.
CREATE DATABASE testdb;
pom.xml
<?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>3.0.1</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>spring-boot-postgresql-mybatis-crud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-boot-postgresql-mybatis-crud</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>17</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>3.0.0</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</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>
schema.sql
CREATE TABLE IF NOT EXISTS users
(
id SERIAL PRIMARY KEY,
first_name varchar(255) not null,
last_name varchar(255) not null,
email_id varchar(255) not null
);
application.properties
Add the following configuration to application.properties file:
spring.datasource.url=jdbc:postgresql://localhost:5432/testdb
spring.datasource.username=postgres
spring.datasource.password=root
spring.sql.init.mode=always
Creating User Bean
package com.knf.dev.demo.model;
public class User {
private Integer id;
private String firstName;
private String lastName;
private String emailId;
public User() {
}
public User(Integer id,String firstName,
String lastName, String emailId) {
super();
this.id=id;
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
}
public Integer getId() {
return id;
}
public void setId(Integer 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
@Insert, @Select, @Update, @Delete: those annotations represent SQL statements to be executed by calling annotated methods.
@Results: A list of Result mappings that contain details of how a particular result column is mapped to a property or field.
@Result: A single result mapping between a column and a property or field.
package com.knf.dev.demo.repository;
import com.knf.dev.demo.model.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
import java.util.Optional;
@Mapper
public interface UserRepository {
@Select("select * from users")
@Results({
@Result(property = "firstName", column = "first_name"),
@Result(property = "lastName", column = "last_name"),
@Result(property = "emailId", column = "email_id")
})
List<User> findAll();
@Select("SELECT * FROM users WHERE id = #{id}")
@Results({
@Result(property = "firstName", column = "first_name"),
@Result(property = "lastName", column = "last_name"),
@Result(property = "emailId", column = "email_id")
})
Optional<User> findById(Integer id);
@Delete("DELETE FROM users WHERE id = #{id}")
int deleteById(Integer id);
@Insert("INSERT INTO users(first_name, last_name, email_id) " +
" VALUES (#{firstName}, #{lastName}, #{emailId})")
int insert(User user);
@Update("Update users set first_name=#{firstName}, " +
" last_name=#{lastName}, email_id=#{emailId} where id=#{id}")
int update(User user);
}
-Exception handling
Create ResourceNotFoundException
package com.knf.dev.demo.exception;
public class ResourceNotFoundException extends RuntimeException{
private static final long serialVersionUID = 1L;
public ResourceNotFoundException(String message) {
super(message);
}
}
Create 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.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(ResourceNotFoundException.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);
}
}
Create CustomErrorResponse
package com.knf.dev.demo.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;
}
}
Create User Rest Controller
package com.knf.dev.demo.controller;
import com.knf.dev.demo.exception.ResourceNotFoundException;
import com.knf.dev.demo.model.User;
import com.knf.dev.demo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
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 Map<String, Boolean> createUser(@RequestBody User user) {
Map<String, Boolean> response = new HashMap<>();
Boolean bool = userRepository.insert(user) > 0 ?
response.put("created", Boolean.TRUE) :
response.put("created", Boolean.FALSE);
return response;
}
// get user by id rest api
@GetMapping("/users/{id}")
public User findUserById(@PathVariable Integer id) {
User user = userRepository.findById(id).
orElseThrow(() -> new ResourceNotFoundException
("User not exist with id :" + id));
return user;
}
// update user rest api
@PutMapping("/users/{id}")
public Map<String, Boolean> updateUser(@PathVariable Integer id,
@RequestBody User userDetails) {
User user = userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException
("User not exist with id :" + id));
userDetails.setId(id);
Map<String, Boolean> response = new HashMap<>();
Boolean bool = userRepository.update(userDetails) > 0 ?
response.put("updated", Boolean.TRUE) :
response.put("updated", Boolean.FALSE);
return response;
}
// delete user rest api
@DeleteMapping("/users/{id}")
public Map<String, Boolean> deleteUser
(@PathVariable Integer id) {
User user = userRepository.findById(id)
.orElseThrow(() -> new ResourceNotFoundException
("User not exist with id :" + id));
Map<String, Boolean> response = new HashMap<>();
Boolean bool = userRepository.deleteById(user.getId()) > 0 ?
response.put("deleted", Boolean.TRUE) :
response.put("deleted", Boolean.FALSE);
return response;
}
}
Run the application - Application.java
package com.knf.dev.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
Application is the entry point that sets up the Spring Boot application. The @SpringBootApplication annotation enables auto-configuration and component scanning.
Step1: Download or clone the source code from GitHub to a local machine - Click here
Step 2: mvn clean install
Step 3: Run the Spring Boot application - mvn spring-boot:run
OR
Run this Spring boot application from
- IntelliJ IDEA IDE by right click - Run 'Application.main()'
- Eclipse/STS - You can right click the project or the Application.java file and run as java application or Spring boot application.
Step1: Download or clone the source code from GitHub to a local machine - Click here
Step 2: mvn clean install
Step 3: Run the Spring Boot application - mvn spring-boot:run
OR
Run this Spring boot application from
- IntelliJ IDEA IDE by right click - Run 'Application.main()'
- Eclipse/STS - You can right click the project or the Application.java file and run as java application or Spring boot application.
Add User-
More....