Creating a Spring Boot CRUD REST API with MySQL and Image Upload – Step-by-Step Guide

Creating a Spring Boot CRUD REST API with MySQL and Image Upload – Step-by-Step Guide

AI Reading

Quick summary of this article

This guide explains how to build a Spring Boot CRUD REST API that connects to a MySQL database and supports image uploads. The tutorial covers setting up the development environment in VS Code, creating the project structure with layers like Entity, DTO, Repository, Service, and Controller, and implementing the full control flow from HTTP requests to database operations.

  • Use VS Code with Java 17+, Maven, MySQL, and extensions like Java Extension Pack, Spring Boot Extension Pack, and Thunder Client for testing.
  • The application.properties file configures MySQL connection, username, password, and enables automatic table updates with Hibernate.
  • The User entity stores id, name, email, and imageUrl fields, while the UserDTO uses MultipartFile to handle image uploads separately from data.
  • The Service layer saves images to an "uploads/" folder with a unique filename and stores the filename in the database.
  • The Controller provides POST, GET, PUT, and DELETE endpoints under "/api/users" for full CRUD operations.

Creating a Spring Boot CRUD REST API with MySQL and Image Upload – Step-by-Step Guide

In today’s full-stack development, building a robust backend API is essential for powering dynamic web or mobile applications. In this tutorial, we’ll walk you through creating a Spring Boot CRUD REST API using MySQL as the database and also handling image upload. Whether you’re building a user management system or an admin dashboard, CRUD operations (Create, Read, Update, Delete) form the backbone of your app.

✅ VS Code Setup

  • Install Java 17+
  • Install Maven
  • Install MySQL Server
  • Install VS Code with these extensions:
  • Java Extension Pack
  • Spring Boot Extension Pack
  • Maven for Java
  • Thunder Client (for API testing)
  • Lombok Support

⚙️ Create Project Using Spring Initializr in VS Code

Open VS Code → Use Spring Initializr Extension → Choose:

  • Project Type: Maven
  • Language: Java
  • Spring Boot: 3.x
  • Dependencies: Spring Web, Spring Data JPA, MySQL Driver, Lombok

📁 Project Structure


src/
├── config/
│   └── SecurityConfig.java
├── controller/
│   └── UserController.java
├── dto/
│   └── UserDTO.java
├── entity/
│   └── User.java
├── repository/
│   └── UserRepository.java
├── service/
│   └── UserService.java
└── SpringAngularCrudApplication.java
  

🔁 Control Flow

Here’s how the control flows through the app:

  • Client (Angular or Postman) sends HTTP requests
  • Controller receives request, maps DTOs, calls Service
  • Service handles business logic and file saving
  • Repository handles DB interaction via JPA
  • Entity represents DB table
  • DTO ensures safe and efficient data transfer

💾 application.properties


spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=yourpassword
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
  

📦 Entity – User.java


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

🧾 DTO – UserDTO.java


@Data
public class UserDTO {
  private Long id;
  private String name;
  private String email;
  private MultipartFile image;
}
  

📁 Repository – UserRepository.java


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

🔧 Service – UserService.java


@Service
public class UserService {
  @Autowired
  private UserRepository userRepository;

  public User saveUser(UserDTO dto) throws IOException {
    User user = new User();
    user.setName(dto.getName());
    user.setEmail(dto.getEmail());
    if (dto.getImage() != null) {
      String fileName = UUID.randomUUID() + "_" + dto.getImage().getOriginalFilename();
      Path path = Paths.get("uploads/" + fileName);
      Files.copy(dto.getImage().getInputStream(), path);
      user.setImageUrl(fileName);
    }
    return userRepository.save(user);
  }

  public List<User> getAllUsers() {
    return userRepository.findAll();
  }

  public void deleteUser(Long id) {
    userRepository.deleteById(id);
  }

  public User updateUser(Long id, UserDTO dto) throws IOException {
    User user = userRepository.findById(id).orElseThrow();
    user.setName(dto.getName());
    user.setEmail(dto.getEmail());
    if (dto.getImage() != null) {
      String fileName = UUID.randomUUID() + "_" + dto.getImage().getOriginalFilename();
      Path path = Paths.get("uploads/" + fileName);
      Files.copy(dto.getImage().getInputStream(), path, StandardCopyOption.REPLACE_EXISTING);
      user.setImageUrl(fileName);
    }
    return userRepository.save(user);
  }
}
  

🌐 Controller – UserController.java


@RestController
@RequestMapping("/api/users")
public class UserController {
  @Autowired
  private UserService userService;

  @PostMapping
  public ResponseEntity<User> createUser(@ModelAttribute UserDTO dto) throws IOException {
    return ResponseEntity.ok(userService.saveUser(dto));
  }

  @GetMapping
  public List<User> getAll() {
    return userService.getAllUsers();
  }

  @PutMapping("/{id}")
  public ResponseEntity<User> update(@PathVariable Long id, @ModelAttribute UserDTO dto) throws IOException {
    return ResponseEntity.ok(userService.updateUser(id, dto));
  }

  @DeleteMapping("/{id}")
  public void delete(@PathVariable Long id) {
    userService.deleteUser(id);
  }
}
  

🗂️ Static File Setup


@Configuration
public class WebConfig implements WebMvcConfigurer {
  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    registry.addResourceHandler("/uploads/**")
            .addResourceLocations("file:uploads/");
  }
}
  

✅ Summary

You’ve now built a complete Spring Boot backend with:

  • REST APIs for user management (CRUD)
  • MySQL as the persistent store
  • Image uploading via MultipartFile
  • Clean project structure with DTO, Entity, Repository, Service, and Controller layers
  • VS Code as your lightweight, full-featured development environment

Leave a Reply

Your email address will not be published. Required fields are marked *