Page cover

Building a CRUD Application with Spring Boot

Spring Boot is a powerful framework for building Java-based web applications. One of its most common uses is to create RESTful APIs that interact with databases. This guide will walk you through creating a simple CRUD (Create, Read, Update, Delete) application using Spring Boot.

Prerequisites

Before you start, ensure you have the following installed:

  1. JDK 11 or later

  2. Maven

  3. An IDE like IntelliJ IDEA or Eclipse

Setting Up the Project

Step 1: Initialize a Spring Boot Project

You can use the Spring Initializr to generate your Spring Boot project. Go to start.spring.io and create a project with the following specifications:

  • Project: Maven

  • Language: Java

  • Spring Boot: 2.5.4 or later

  • Group: com.example

  • Artifact: crud-demo

  • Dependencies: Spring Web, Spring Data JPA, H2 Database, Lombok

Download the generated project and unzip it. Open the project in your IDE.

Step 2: Project Structure

Your project structure should look something like this:

crud-demo/
├── src/
│   ├── main/
│   │   ├── java/
│   │   │   └── com/example/cruddemo/
│   │   │       ├── CrudDemoApplication.java
│   │   │       ├── controller/
│   │   │       ├── model/
│   │   │       └── repository/
│   │   └── resources/
│   │       ├── application.properties
│   │       └── data.sql
└── pom.xml

Creating the CRUD Application

Step 3: Define the Entity

Create a new package model and define your entity class User:

package com.example.cruddemo.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

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

Here, we use Lombok annotations (@Data, @NoArgsConstructor, @AllArgsConstructor) to generate boilerplate code like getters, setters, and constructors.

Step 4: Create the Repository

Create a new package repository and define the repository interface:

package com.example.cruddemo.repository;

import com.example.cruddemo.model.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

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

The UserRepository extends JpaRepository, which provides CRUD operations for the User entity.

Step 5: Create the Controller

Create a new package controller and define the controller class:

package com.example.cruddemo.controller;

import com.example.cruddemo.model.User;
import com.example.cruddemo.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

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

    @Autowired
    private UserRepository userRepository;

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

    // Get a single user by ID
    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable Long id) {
        User user = userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id));
        return ResponseEntity.ok(user);
    }

    // Create a new user
    @PostMapping
    public User createUser(@RequestBody User user) {
        return userRepository.save(user);
    }

    // Update an existing user
    @PutMapping("/{id}")
    public ResponseEntity<User> updateUser(@PathVariable Long id, @RequestBody User userDetails) {
        User user = userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id));
        user.setName(userDetails.getName());
        user.setEmail(userDetails.getEmail());
        User updatedUser = userRepository.save(user);
        return ResponseEntity.ok(updatedUser);
    }

    // Delete a user
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
        User user = userRepository.findById(id).orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id));
        userRepository.delete(user);
        return ResponseEntity.noContent().build();
    }
}

Step 6: Handle Exceptions

Create a custom exception and exception handler for resource not found cases. In the controller package, add the following classes:

ResourceNotFoundException.java:

package com.example.cruddemo.controller;

public class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException(String message) {
        super(message);
    }
}

GlobalExceptionHandler.java:

package com.example.cruddemo.controller;

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.bind.annotation.ResponseStatus;

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public ResponseEntity<String> handleResourceNotFoundException(ResourceNotFoundException ex) {
        return new ResponseEntity<>(ex.getMessage(), HttpStatus.NOT_FOUND);
    }
}

Step 7: Configure the Application

Open src/main/resources/application.properties and configure the H2 database:

spring.datasource.url=jdbc:h2:mem:testdb
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=password
spring.h2.console.enabled=true
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
spring.jpa.hibernate.ddl-auto=update

Step 8: Seed the Database

(Optional) Create a data.sql file in the src/main/resources directory to seed the database with initial data:

INSERT INTO user (name, email) VALUES ('John Doe', 'john.doe@example.com');
INSERT INTO user (name, email) VALUES ('Jane Smith', 'jane.smith@example.com');

Running the Application

Run the application by executing the CrudDemoApplication class. Your application should be accessible at http://localhost:8080.

Testing the Endpoints

Use a tool like Postman or curl to test the endpoints:

  • Get all users:

    curl -X GET http://localhost:8080/api/users
  • Get user by ID:

    curl -X GET http://localhost:8080/api/users/1
  • Create a new user:

    curl -X POST http://localhost:8080/api/users -H "Content-Type: application/json" -d '{"name":"Alice Brown","email":"alice.brown@example.com"}'
  • Update a user:

    curl -X PUT http://localhost:8080/api/users/1 -H "Content-Type: application/json" -d '{"name":"John Doe Jr.","email":"john.doe.jr@example.com"}'
  • Delete a user:

    curl -X DELETE http://localhost:8080/api/users/1

Conclusion

You've now built a complete CRUD application with Spring Boot. This basic structure can be expanded with more features, such as authentication, validation, and advanced querying. Spring Boot's simplicity and power make it an excellent choice for developing RESTful APIs. Happy coding!

Last updated