@PutMapping vs @PatchMapping in Spring Boot

1. Introduction

In Spring Boot, handling HTTP requests is a core functionality facilitated by various annotations in the Spring Web module. Two such annotations are @PutMapping and @PatchMapping, which are used for handling HTTP PUT and PATCH requests respectively. Understanding the differences and appropriate usage of these two can significantly affect the design and functionality of your web application.

Key Differences

1. Usage: The @PutMapping annotation maps HTTP PUT requests, which are intended for updating an entire resource or creating it if it doesn't exist. @PatchMapping annotation maps HTTP PATCH requests, which are used for making partial changes to a resource, typically modifying specific fields.

2. Idempotence: PUT requests are idempotent, meaning making multiple identical requests will produce the same result. PATCH requests can be non-idempotent, varying the outcome based on the state of the target resource.

3. Use Case: Use @PutMapping when the client sends a complete updated version of a resource. Use @PatchMapping when the client sends only the changes to the resource.

Example

// Step 1: Model Class
public class Employee {
    private Long id;
    private String name;
    private String email;
    // Getters and Setters
}

// Step 2: Repository Class
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}

// Step 3: Service Class
@Service
public class EmployeeService {
    @Autowired
    private EmployeeRepository repository;

    public Employee updateEmployee(Long id, Employee details) {
        Employee employee = repository.findById(id).orElseThrow(() -> new RuntimeException("Employee not found"));
        employee.setName(details.getName());
        employee.setEmail(details.getEmail());
        return repository.save(employee);
    }

    public Employee patchEmployee(Long id, Map<String, Object> updates) {
        Employee employee = repository.findById(id).orElseThrow(() -> new RuntimeException("Employee not found"));
        updates.forEach((key, value) -> {
            Field field = ReflectionUtils.findField(Employee.class, key);
            field.setAccessible(true);
            ReflectionUtils.setField(field, employee, value);
        });
        return repository.save(employee);
    }
}

// Step 4: Controller Class
@RestController
@RequestMapping("/employees")
public class EmployeeController {
    @Autowired
    private EmployeeService service;

    @PutMapping("/{id}")
    public ResponseEntity<Employee> updateEmployee(@PathVariable Long id, @RequestBody Employee employee) {
        return ResponseEntity.ok(service.updateEmployee(id, employee));
    }

    @PatchMapping("/{id}")
    public ResponseEntity<Employee> patchEmployee(@PathVariable Long id, @RequestBody Map<String, Object> updates) {
        return ResponseEntity.ok(service.patchEmployee(id, updates));
    }
}

Explanation:

1. The model class Employee defines the structure of the employee resource.

2. The repository class extends JpaRepository to provide CRUD operations for the Employee entities.

3. The service class contains business logic for updating and patching employees using methods updateEmployee and patchEmployee.

4. The controller class defines the endpoints for PUT and PATCH operations, calling the respective service methods.

5. The PUT operation updates all attributes of the employee, while the PATCH operation only updates the attributes provided in the request.

Conclusion

In Spring Boot, @PutMapping and @PatchMapping are annotations used to handle HTTP PUT and PATCH requests, respectively: 

  • @PutMapping is used for mapping HTTP PUT requests onto specific handler methods. PUT is typically used to update a resource entirely or create a new resource if it does not exist. 
  • @PatchMapping is used for mapping HTTP PATCH requests onto specific handler methods. PATCH is used for making partial updates to an existing resource, modifying only the fields that are provided in the request. 

These annotations help define clearer and more precise routing in your Spring Boot controllers.

Comments