Example - Employee Portal

About

We have a Employee Portal where we can manage employee data, search using various fields, and sort in a paginated manner, the key is to build an efficient and scalable Spring Boot API that supports:

  • Storing and retrieving employee data.

  • Searching and filtering by multiple fields.

  • Sorting by one or more fields.

  • Paginated results.

Solution

1. Entity Model: Employee

We will begin by defining an Employee entity class. It will have fields like id, name, department, salary, etc.

import javax.persistence.Entity;
import javax.persistence.Id;

@Entity
public class Employee {

    @Id
    private Long id;
    private String name;
    private String department;
    private Double salary;
    private String email;
    private String phoneNumber;

    // Getters and Setters
}

2. Repository Layer

Spring Data JPA provides a powerful mechanism to interact with the database without needing to write explicit SQL or JPQL queries. We will use JpaRepository to handle basic CRUD operations and enable custom queries.

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
    // Additional custom query methods can be added as needed
}

3. Service Layer for Pagination, Sorting, and Searching

In the service layer, we will define methods for retrieving paginated, sorted, and filtered employee data.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class EmployeeService {

    @Autowired
    private EmployeeRepository employeeRepository;

    // Fetch all employees with pagination, sorting, and filtering
    public Page<Employee> getEmployees(String name, String department, Double salaryMin, Double salaryMax, Pageable pageable) {
        return employeeRepository.findAll(EmployeeSpecifications.withFilters(name, department, salaryMin, salaryMax), pageable);
    }
}

4. Specification for Filtering

To support dynamic filtering based on user input, we can use JPA Specifications. This allows us to build flexible queries without writing JPQL or SQL manually.

import org.springframework.data.jpa.domain.Specification;
import javax.persistence.criteria.*;

public class EmployeeSpecifications {

    public static Specification<Employee> withFilters(String name, String department, Double salaryMin, Double salaryMax) {
        return (root, query, criteriaBuilder) -> {
            Predicate predicate = criteriaBuilder.conjunction();

            if (name != null && !name.isEmpty()) {
                predicate = criteriaBuilder.and(predicate, criteriaBuilder.like(root.get("name"), "%" + name + "%"));
            }

            if (department != null && !department.isEmpty()) {
                predicate = criteriaBuilder.and(predicate, criteriaBuilder.equal(root.get("department"), department));
            }

            if (salaryMin != null) {
                predicate = criteriaBuilder.and(predicate, criteriaBuilder.greaterThanOrEqualTo(root.get("salary"), salaryMin));
            }

            if (salaryMax != null) {
                predicate = criteriaBuilder.and(predicate, criteriaBuilder.lessThanOrEqualTo(root.get("salary"), salaryMax));
            }

            return predicate;
        };
    }
}

5. Controller Layer

In the controller, we expose the API endpoints to search, filter, sort, and paginate employee data.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/employees")
public class EmployeeController {

    @Autowired
    private EmployeeService employeeService;

    // Get employees with pagination, sorting, and filtering
    @GetMapping
    public ResponseEntity<Page<Employee>> getEmployees(
            @RequestParam(required = false) String name,
            @RequestParam(required = false) String department,
            @RequestParam(required = false) Double salaryMin,
            @RequestParam(required = false) Double salaryMax,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "10") int size,
            @RequestParam(defaultValue = "id") String sortBy,
            @RequestParam(defaultValue = "asc") String sortDirection
    ) {
        try {
            // Create Sort and Pageable objects
            Sort sort = Sort.by(Sort.Order.by(sortBy).with(Sort.Direction.fromString(sortDirection)));
            Pageable pageable = PageRequest.of(page, size, sort);

            // Fetch employees based on provided filters
            Page<Employee> employees = employeeService.getEmployees(name, department, salaryMin, salaryMax, pageable);

            // If the employees page is empty, return a 204 No Content response
            if (employees.isEmpty()) {
                return new ResponseEntity<>(HttpStatus.NO_CONTENT);
            }

            // Return employees with a 200 OK status
            return new ResponseEntity<>(employees, HttpStatus.OK);

        } catch (Exception e) {
            // If there is any error, return a 500 Internal Server Error
            return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
        }
    }
}

API Example

  • GET /employees: Retrieves a paginated, filtered, and sorted list of employees.

Example Request

GET /employees?name=John&department=Engineering&salaryMin=50000&page=1&size=10&sortBy=name&sortDirection=desc

Example Response

{
    "content": [
        {
            "id": 1,
            "name": "John Doe",
            "department": "Engineering",
            "salary": 60000,
            "email": "john.doe@example.com",
            "phoneNumber": "123-456-7890"
        },
        {
            "id": 2,
            "name": "John Smith",
            "department": "Engineering",
            "salary": 55000,
            "email": "john.smith@example.com",
            "phoneNumber": "098-765-4321"
        }
    ],
    "pageable": {
        "sort": {
            "unsorted": false,
            "sorted": true,
            "empty": false
        },
        "pageSize": 10,
        "pageNumber": 1,
        "offset": 10,
        "unpaged": false,
        "paged": true
    },
    "totalPages": 5,
    "totalElements": 50,
    "last": false,
    "first": false,
    "numberOfElements": 10,
    "size": 10,
    "number": 1,
    "sort": {
        "sorted": true,
        "unsorted": false,
        "empty": false
    }
}

Last updated

Was this helpful?