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