Spring Data JDBC + Azure Database for MySQL - Build REST CRUD APIs

In this section, we will learn how to build REST CRUD APIs with Spring BootSpring Data JDBC and Microsoft Azure Database for MySQL.


A little bit of Background

Azure Database for MySQL Single Server

Azure Database for MySQL Single Server is a fully managed database service designed for minimal customization. The single server platform is designed to handle most of the database management functions such as patching, backups, high availability, and security with minimal user configuration and control. The architecture is optimised for built-in high availability with 99.99% availability in a single availability zone. It supports the community version of MySQL 5.6 (retired), 5.7 and 8.0. The service is generally available today in a wide variety of Azure regions.

Spring Boot

Spring Boot makes it easy to create stand-alone, production-grade Spring-based Applications that you can "just run". 
More Info - Spring Boot


Spring Data JDBC

Spring Data JDBC Extensions is part of the umbrella Spring Data project. The JDBC support in the Spring Framework is extensive and covers the most commonly used features.

After completing this tutorial what we will build? 

We will build REST APIs  CRUD features: 



Step 1: Sign in to Azure Portal and create a resource group

Sign in to Azure portal https://portal.azure.com/#home and find "Resource groups" like below.



Then, create a resource group like the one below.


Here the resource group name is "Knowledgefactory". Create a resource group by clicking the "Review + create " button.



Step 2: Create an Azure Database for MySQL Single Server

Select "Azure Database for MySQL servers",

You will be taken to a page like the below image, Then click on the "Create Azure Database for MySQL Server" button.

You will be taken to a page like the below image,
Select Single Server, Then click on the Single Server"Create" button.

You will be taken to a page like the below image,
Select/Enter necessary information like the above image and then, click on the "Review + create" button. 

Then click on the "Create" button.

Now, You can see "Deployment is in progress" like the below image.

Once deployment is completed you can see the "Your deployment is complete" page like the below image.

Click on the "Connection strings",
Copy the JDBC connection string and keep it safe for future purposes.

Whitelisting IP Address for Access to Azure MySQL DB, like the below image.
Then click on the "Save" button



Step 3: 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-data-jdbc-azure-mysql-crud. Here I selected the Maven project - language Java - Spring Boot 2.7.3 and add Spring web dependency, Spring JDBC API, and MySQL Driver. 


Then, click on the Generate button. When we click on the Generate button, it starts packing the project in a .zip(spring-data-jdbc-azure-mysql-crud.zip) file and downloads the project. 
Then, Extract the Zip file.

Import the project on your favourite IDE,

Final Project Directory:




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. 

<?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.7.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>spring-data-jdbc-azure-mysql-crud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-data-jdbc-azure-mysql-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-data-jdbc</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>



schema.sql: Creating a table for 'user'

Spring Boot can automatically create the schema (DDL scripts) of your DataSource and initialize it (DML scripts). It loads SQL from the standard root classpath locations: schema. sql and data. sql , respectively.
DROP TABLE IF EXISTS user;

CREATE TABLE user (
id serial PRIMARY KEY,
first_name VARCHAR ( 50 ) NOT NULL,
last_name VARCHAR ( 50 ) NOT NULL,
email VARCHAR ( 255 ) NOT NULL
);


application.properties

The following properties are needed to configure MySQL with Spring Boot. 

The property spring.datasource.initialization-mode from Spring boot verion 2.7 and onwards is not any more depracated. It has been completely removed! So the change into the replacement property spring.sql.init.mode is a must do from now on.
Example: spring.sql.init.mode=always
logging.level.org.springframework.jdbc.core=DEBUG

spring.datasource.url=jdbc:mysql://<servername>.mysql.database.azure.com:3306/test?createDatabaseIfNotExist=true
spring.datasource.username=knfAdmin@knf-server
spring.datasource.password=<password>

spring.sql.init.mode=
always
**Important note** Do not publish the fields directly for security. It would be a good choice to define these variables as environment variables or use the Azure Key Vault. 


Creating the Model User

package com.knf.dev.demo.model;

import org.springframework.data.annotation.Id;

public class User {
@Id
private Long id;

private String firstName;

private String lastName;

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

package com.knf.dev.demo.repository;

import com.knf.dev.demo.model.User;
import org.springframework.data.repository.CrudRepository;

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.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.util.Date;

@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(UserNotFound.class)
public ResponseEntity<ErrorMessage>
userNotFound(Exception ex, WebRequest request) {
var errors =
new ErrorMessage(404, new Date(),
ex.getMessage(), "User Not Found");

return new ResponseEntity<>
(errors, HttpStatus.NOT_FOUND);
}
}



Custom Exception - UserNotFound

package com.knf.dev.demo.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.exception;

import java.util.Date;

public record ErrorMessage
(Integer statusCode,
Date timestamp,
String message,
String 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.controller;

import com.knf.dev.demo.exception.UserNotFound;
import com.knf.dev.demo.model.User;
import com.knf.dev.demo.repository.UserRepository;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

@RestController
@RequestMapping("/api/v1/users")
public class UserController {

private final UserRepository userRepository;

public UserController(UserRepository userRepository)
{
this.userRepository = userRepository;
}

// Create user
@PostMapping
public ResponseEntity<User> createUser
(@RequestBody User user) {

User newuser = new User(user.getFirstName(),
user.getLastName(), user.getEmail());
userRepository.save(newuser);
return new ResponseEntity<>(newuser, HttpStatus.CREATED);

}

// 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() {

List<User> users = new ArrayList<User>();
userRepository.findAll().forEach(users::add);
return new ResponseEntity<>(users, HttpStatus.OK);

}

// 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;

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

@SpringBootApplication
public class SpringDataJdbcAzureMysqlCrudApplication {

public static void main(String[] args) {
SpringApplication.run(SpringDataJdbcAzureMysqlCrudApplication.class, args);
}

}



Step 4: Local Setup and Run the application

Step 1: 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


Step 5: Test the APIs using postman

1. Add User:


2. Get User By Id:


3. Update User:


4. Get All Users:


5. Delete User:

Download the complete source code - click here

Comments

Popular posts from this blog

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

Java, Spring Boot Mini Project - Library Management System - Download

Java - DES Encryption and Decryption example

Java - Blowfish Encryption and decryption Example

Google Cloud Storage + Spring Boot - File Upload, Download, and Delete

ReactJS - Bootstrap - Buttons

Top 5 Java ORM tools - 2024

Spring Boot 3 + Spring Security 6 + Thymeleaf - Registration and Login Example

File Upload, Download, And Delete - Azure Blob Storage + Spring Boot Example

Java - How to Count the Number of Occurrences of Substring in a String