Getting Started with CRUD Operations in Spring Boot and MySQL: A Beginner’s Guide

Matheshyogeswaran
LinkIT
Published in
5 min readOct 10, 2023

An In-Depth Introduction to Creating, Reading, Updating, and Deleting Data in Spring Boot and MySQL for Beginners

Artwork by Author

Welcome to this beginner-friendly tutorial, where we’ll explore the world of CRUD applications built with Spring Boot. Our aim is to equip you with a solid understanding of constructing CRUD operations while adhering to best practices in project organization.

Getting Started with Spring Boot

Let’s jump right in by creating a basic Spring Boot application. Follow these steps:

Go to Spring Initializr.
Choose the Maven project option.
Select the ‘Spring Web’ and MySQL driver dependencies.
Click the ‘Generate’ button to initiate project generation.

Creating Spring Boot Project in Spring Initializr

Organizing Your Project

Once the project is generated, open it in IntelliJ IDEA. Our first task is to establish a well-structured file hierarchy. Your project structure should look like this:

src
├── main
│ ├── java
│ │ └── com
│ │ └── yourcompany
│ │ └── yourapp
│ │ ├── controller
│ │ │ └── UserController.java
│ │ ├── model
│ │ │ └── User.java
│ │ ├── repository
│ │ │ └── UserRepository.java
│ │ ├── service
│ │ │ ├── UserService.java
│ │ │ └── impl
│ │ │ └── UserServiceImpl.java
│ │ └── Application.java
│ ├── resources
│ │ ├── application.properties
│ │ └── static (for static resources like CSS and JS)
│ │ └── templates (for HTML templates if using server-side rendering)
│ └── sql (for database schema scripts)
└── test
  • Controller: Contains the REST API controllers for handling HTTP requests and responses.
  • Model: Defines the data models or entities of your application.
  • Repository: Provides interfaces for database interaction using Spring Data JPA.
  • Service: Implements business logic and acts as an intermediary between controllers and repositories.
  • Impl: Contains the actual implementations of service interfaces.
  • Resources: Contains application configuration files and static resources.
  • Application.properties: Configuration file for Spring Boot application properties like database configuration.

The Entity: User.java

Let’s create the entity class that represents our user:

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.Data;


@Entity
@Data
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;
private String address;

}

UserRepository.java

Our UserRepository interfaces with the database:


import com.basic.crud.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

public interface UserRepository extends JpaRepository<User, Long> {
}

Implementing Business Logic: UserService.java

The UserService interface defines essential operations:

package com.basic.crud.service;

import com.basic.crud.model.User;

import java.util.List;

public interface UserService {
List<User> getAllEntities();
User getEntityById(Long id);
User createEntity(User entity);
User updateEntity(Long id, User entity);
void deleteEntity(Long id);
}

UserServiceImpl.java

The UserServiceImpl brings the logic:

package com.basic.crud.service;

import com.basic.crud.model.User;
import com.basic.crud.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {

private final UserRepository repository;

@Autowired
public UserServiceImpl(UserRepository repository) {
this.repository = repository;
}

@Override
public List<User> getAllEntities() {
return repository.findAll();
}

@Override
public User getEntityById(Long id) {
return repository.findById(id).orElse(null);
}

@Override
public User createEntity(User entity) {
return repository.save(entity);
}

@Override
public User updateEntity(Long id, User entity) {
if (repository.existsById(id)) {
entity.setId(id);
return repository.save(entity);
}
return null;
}

@Override
public void deleteEntity(Long id) {
repository.deleteById(id);
}
}

UserController.java

REST endpoints are orchestrated in UserController:

package com.basic.crud.controller;

import com.basic.crud.model.User;
import com.basic.crud.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

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

private final UserService service;

@Autowired
public UserController(UserService service) {
this.service = service;
}

@GetMapping
public List<User> getAllEntities() {
return service.getAllEntities();
}

@GetMapping("/{id}")
public User getEntityById(@PathVariable Long id) {
return service.getEntityById(id);
}

@PostMapping
public User createEntity(@RequestBody User entity) {
return service.createEntity(entity);
}

@PutMapping("/{id}")
public User updateEntity(@PathVariable Long id, @RequestBody User entity) {
return service.updateEntity(id, entity);
}

@DeleteMapping("/{id}")
public void deleteEntity(@PathVariable Long id) {
service.deleteEntity(id);
}
}

Database Configuration: application.properties

Configure your database properties:

spring.datasource.url=jdbc:mysql://localhost:3306/yourDatabaseName
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.hibernate.ddl-auto=update

Understanding the Architecture

So, upon completing these steps, you have successfully implemented the CRUD operations. Now, let’s dive into how this file structure functions. First, within the controller, API calls are initiated. These API calls are then routed to the corresponding methods in the service layer. The service layer acts as a bridge between the controller and the actual business logic, decoupling the two components.

Inside the service layer, the defined methods are implemented within the impl package. This separation of concerns allows for a cleaner and more organized structure. The implementation layer handles the core business logic, such as retrieving data from the database, performing necessary calculations, and managing data modifications.

By adhering to this structure, your application gains a modular design that enhances maintainability and scalability. The division between the controller, service, and implementation layers enables better code organization and easier debugging. Additionally, this architecture aligns with the principles of the Spring framework, facilitating the development of robust and efficient applications.

In summary, the controller initiates API calls, which are then processed by the service layer. The service layer interfaces with the implementation layer to handle the actual business logic. Embracing this layered architecture contributes to the development of a more structured, maintainable, and comprehensible CRUD application.

And there you have it — an illustrative example of creating a user

Creating a User in Postman

Conclusion

In conclusion, this tutorial has guided us through creating a fundamental CRUD application using Spring Boot. By following the steps outlined here, we’ve grasped the importance of proper project structuring, entity definition, repository interfaces, service layers, and RESTful controllers.

To access the complete code for this tutorial, please visit the GitHub repository. If you’d like to connect, feel free to find me on LinkedIn.

Happy coding, and best of luck with your projects!

--

--

Matheshyogeswaran
LinkIT
Writer for

Undergraduate at the University of Moratuwa, Trainee Software Engineer, and tech enthusiast exploring cloud computing and software development.