Spring Boot, MySQL, JPA, Hibernate Restful CRUD API Tutorial

In this tutorial, we’ll build a Restful CRUD API for a simple user management application. We’ll first build the APIs to create, retrieve, update and delete a user, and then test them using postman.
This Spring Boot project is upgraded to Spring Boot 3 and Java 17.

Spring Boot has taken the Spring framework to the next level. It has drastically reduced the configuration and setup time required for spring projects.
Learn Spring boot at https://www.javaguides.net/p/spring-boot-tutorial.html.
You can set up a project with almost zero configuration and start building the things that actually matter to your application.
If you are new to Spring boot and want to get started with it quickly, then this blog post is for you.

Video Tutorial

This tutorial I have explained very well in below video tutorial:

What we’ll build

We are building a simple User Management Application which has below CRUD Rest APIs. Following five REST APIs (Controller handler methods) are created for User resource:

High-level architecture of Spring boot project

1. Creating a Spring Boot Application

There are many ways to create a Spring Boot application. You can refer below articles to create a Spring Boot application.
Refer to the next step to create a project packaging structure.

2. Maven 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>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>

3. Configuring MySQL Database

Since we’re using MySQL as our database, we need to configure the database URL, username, and password so that Spring can establish a connection with the database on startup. Open src/main/resources/application.properties file and add the following properties to it:
spring.datasource.url = jdbc:mysql://localhost:3306/usersDB?useSSL=false
spring.datasource.username = root
spring.datasource.password = root


## Hibernate Properties
# The SQL dialect makes Hibernate generate better SQL for the chosen database
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQLDialect

# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto = update
Don’t forget to change the spring.datasource.username and spring.datasource.password as per your MySQL installation. Also, create a database named usersDB in MySQL before proceeding to the next section.
You don’t need to create any tables. The tables will automatically be created by hibernate from the User entity that we will define in the next step. This is made possible by the property spring.jpa.hibernate.ddl-auto = update.

4. Create User JPA Entity

Let's create a User model or domain class with the following fields: 
  • id - primary key
  • firstName - user first name
  • lastName - user last name
  • emailId - user email ID
package net.javaguides.springboot.entity;

import jakarta.persistence.*;

@Entity
@Table(name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    @Column(name = "first_name")
    private String firstName;

    @Column(name = "last_name")
    private String lastName;

    @Column(name = "email")
    private String email;

    public User() {

    }

    public User(String firstName, String lastName, String email) {
        super();
        this.firstName = firstName;
        this.lastName = lastName;
        this.email = email;
    }

    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;
    }
}
All your domain models must be annotated with @Entity annotation. It is used to mark the class as a persistent Java class.
@Table annotation is used to provide the details of the table that this entity will be mapped to.
@Id annotation is used to define the primary key.
@GeneratedValue annotation is used to define the primary key generation strategy. In the above case, we have declared the primary key to be an Auto Increment field.
@Column annotation is used to define the properties of the column that will be mapped to the annotated field. You can define several properties like name, length, nullable, updateable, etc.

5. Define UserRepository

Let's create a UserRepository to access User's data from the database.
Well, Spring Data JPA has comes with a JpaRepository interface which defines methods for all the CRUD operations on the entity, and a default implementation of JpaRepository called SimpleJpaRepository.
package net.javaguides.springboot.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import net.javaguides.springboot.entity.User;

@Repository
public interface UserRepository extends JpaRepository<User, Long>{

}

6. Creating Custom Business Exception

We’ll define the Rest APIs for creating, retrieving, updating, and deleting a User in the next step.
The APIs will throw a ResourceNotFoundException whenever a User with a given id is not found in the database.
Following is the definition of ResourceNotFoundException:
package net.javaguides.springboot.exception;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.NOT_FOUND)
public class ResourceNotFoundException extends RuntimeException {

    private static final long serialVersionUID = 1 L;

    public ResourceNotFoundException(String message) {
        super(message);
    }
}

7. Creating UserController - Building CRUD Rest APIs

Let's create the REST APIs for creating, retrieving, updating and deleting a User:
package net.javaguides.springboot.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
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 net.javaguides.springboot.entity.User;
import net.javaguides.springboot.exception.ResourceNotFoundException;
import net.javaguides.springboot.repository.UserRepository;

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

    @Autowired
    private UserRepository userRepository;

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

    // get user by id
    @GetMapping("/{id}")
    public User getUserById(@PathVariable(value = "id") long userId) {
        return this.userRepository.findById(userId)
            .orElseThrow(() - > new ResourceNotFoundException("User not found with id :" + userId));
    }

    // create user
    @PostMapping
    public User createUser(@RequestBody User user) {
        return this.userRepository.save(user);
    }

    // update user
    @PutMapping("/{id}")
    public User updateUser(@RequestBody User user, @PathVariable("id") long userId) {
        User existingUser = this.userRepository.findById(userId)
            .orElseThrow(() - > new ResourceNotFoundException("User not found with id :" + userId));
        existingUser.setFirstName(user.getFirstName());
        existingUser.setLastName(user.getLastName());
        existingUser.setEmail(user.getEmail());
        return this.userRepository.save(existingUser);
    }

    // delete user by id
    @DeleteMapping("/{id}")
    public ResponseEntity < User > deleteUser(@PathVariable("id") long userId) {
        User existingUser = this.userRepository.findById(userId)
            .orElseThrow(() - > new ResourceNotFoundException("User not found with id :" + userId));
        this.userRepository.delete(existingUser);
        return ResponseEntity.ok().build();
    }
}

8. Running the Application

We have successfully developed all the CRUD Rest APIs for the User model. Now it's time to deploy our application in a servlet container(embedded tomcat). 
Two ways we can start the standalone Spring boot application. 
1. From the root directory of the application and type the following command to run it -
$ mvn spring-boot:run
2. From your IDE, run the SpringBootCrudRestApplication.main() method as a standalone Java class that will start the embedded Tomcat server on port 8080 and point the browser to http://localhost:8080/.

9. Demo

The demo of this tutorial covered in below YouTube video tutorial:

10. Conclusion

Congratulations guys! We successfully built a Restful CRUD API using Spring Boot, MySQL, JPA, and Hibernate.

You can find the source code for this tutorial on my GitHub repository. Feel free to clone the repository and build upon it.

Thank you for reading. Please ask any questions in the comment section below.

Comments

  1. Very useful and informative tutorial.

    ReplyDelete
  2. how i can coonect my mysql connection in mysql workbench

    ReplyDelete
  3. Replies
    1. localhost. Watch video tutorial, you will get everything that you want.

      Delete
  4. When I run this, I get an error saying "Error creating bean with name 'entityManagerFactory'"

    Do you have any idea what this means? I didn't change anything in the provided code except for the username and password for my local mysql server

    ReplyDelete
    Replies
    1. Make sure that MySQL server is running in your machine and you have configured the same in spring boot project. Typical we get this error when spring boot don't able connect to MySQL server due to configuration issue.

      Delete
  5. Hey Ramesh. Great work once again. I am understanding things on a high level but when runtime exceptions arise it is hard for me to find the underlying problems that are causing the exceptions. What do you think I should do? Should I read the documentation on SPring core or is that overkill? How about your spring core blog? WOuld that be enough for me to understand how spring boot works under the hood?

    ReplyDelete
    Replies
    1. Yeah. You can learn Spring core from my blog which will lead you to understand spring boot internals and how spring boot works behind the scene.

      Delete
    2. ok Ramesh ty for ur advice please continue posting videos on youtube its very helpful

      Delete
    3. Sure buddy. Connect with me social media.

      Delete
  6. java.sql.SQLNonTransientConnectionException: CLIENT_PLUGIN_AUTH is required
    java.sql.SQLNonTransientConnectionException: CLIENT_PLUGIN_AUTH is required
    Caused by: com.mysql.cj.exceptions.UnableToConnectException: CLIENT_PLUGIN_AUTH is required

    ReplyDelete
  7. Hi Ramesh
    I am getting the below error
    java.lang.NullPointerException: Cannot invoke "com.tool.springboot.repository.UserRepository.save(Object)" because "this.userRepository" is null

    ReplyDelete

Post a Comment

Leave Comment