Skip to main content

About General Specification Library

Introduction

In application development, dynamic queries based on various parameters are often necessary. Spring Data JPA offers a solution for creating such dynamic queries through Specifications. This document focuses on utilizing the GeneralSpecification class to generate dynamic queries efficiently with Spring Data JPA.

Prerequisites

Before proceeding, ensure you have:

  • Basic knowledge of Java and Spring Boot.
  • Understanding of Spring Data JPA and Specifications.

GeneralSpecification Overview

GeneralSpecification is a generic class that implements the Specification interface provided by Spring Data JPA. It facilitates dynamic query generation based on search criteria provided through a DataManipulationModel.

DataManipulationModel: Overview

The DataManipulationModel encapsulates filters and sorting criteria.

public class DataManipulationModel {

/**
* list of SortDataModel, The sorting will be performed sequentially based on the order of the
* models in the list. The first added model will be executed first,
* followed by the next, and so on.
*/
private List<SortDataModel> sortDataModels;

/**
* Can be FilterCriteria or FilterGroup.
**/
private Filter criteria;
}
  • criteria: Holds search criteria, which can be either a FilterCriteria or a FilterGroup.

    • FilterCriteria: Represents a single filter condition. It can be instantiated using the condition(fieldName, operation, fieldValue) method.
package com.aya.search.model;

import lombok.Getter;

/**
* Filter Criteria.
*
* @author Ayah Refai
* @since 03/04/2024
*/
@Getter
public final class FilterCriteria implements Filter {

/**
* should match the instance variables of your JPA entity.
* If you need to filter based on a field inside a related object,
* you can reference it using dot notation
**/
private final String fieldName;

/**
* The operation to apply (e.g., EQUALS, GREATER_THAN) {@link Operation}
*/
private final Operation operation;

/**
* The value(s) to compare the field against.
*/
private final Object[] fieldValue;

}
  • FilterGroup: Represents a group of filter conditions combined with logical operators (AND/OR). It can be instantiated using the and(FilterCriteria|FilterGroup) or or(FilterCriteria|FilterGroup) method.
package com.aya.search.model;

import lombok.Getter;
import java.util.List;

/**
* Filter Group.
*
* @author Ayah Refai
* @since 05/24/2024
*/
@Getter
public final class FilterGroup implements Filter {

/**
* This defines the logical operation that combines the filters within the group.
* It can be either "AND" or "OR" {@link Condition}
*/
private final Condition condition;

/**
* This is a list of filters that can either be individual FilterCriteria or other FilterGroup objects.
* This means you can nest groups of filters to create complex filtering logic.
* <p>can be list of {@link FilterCriteria} or {@link FilterGroup}.</p>
*/
private final List<com.aya.search.model.Filter> conditions;
}
  • SortDataModel: Represents sorting criteria with a field name and sort order. It can be instantiated using the asc(fieldName) or desc(fieldName) methods.
package com.aya.search.model;

import lombok.Getter;

/**
* sort data model.
*
* @author Ayah Refai
* @since 03/04/2024
*/
@Getter
public final class SortDataModel {

/**
* should match the instance variables of your JPA entity.
* If you need to sorted based on a field inside a related object,
* you can reference it using dot notation
**/
private final String sortField;

/**
* The sort order to apply {@link SortOrder};
*/
private final SortOrder sortOrder;
}

Usage

Adding Dependencies

Ensure that you include the necessary dependency in your project's Maven pom.xml.


<dependencies>
<!-- Other dependencies -->
<dependency>
<groupId>com.aya.specification</groupId>
<artifactId>aya-search-lib</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>

Creating DataManipulationModel

Instantiate a DataManipulationModel object encapsulating your search and sort criteria.

public static void main(String... args) {
DataManipulationModel dataManipulationModel = new DataManipulationModel();
dataManipulationModel.setSortModel(asc("gpa"), desc("firstName"));
dataManipulationModel.setCriteria(
and(
condition("id", Operation.IN, 1, 2, 3, 4),
condition("firstName", Operation.LIKE, "%a%"),
or(
condition("id", Operation.IN, 11, 12, 13, 14),
condition("firstName", Operation.LIKE, "%s%")
)
)
);
}

Creating GeneralSpecification

Instantiate a GeneralSpecification object with the DataManipulationModel.

GeneralSpecification<Student> studentGeneralSpecification = new GeneralSpecification<>(dataManipulationModel);

Using GeneralSpecification with Spring Data JPA Repository

Pass the GeneralSpecification object to the findAll method of your Spring Data JPA repository along with a Pageable object for pagination.

List<Student> students = studentRepository.findAll(studentGeneralSpecification);
note

Ensure that your studentRepository implements JpaSpecificationExecutor.

Example

Here's an example demonstrating the usage of GeneralSpecification in a service method to retrieve paginated results based on dynamic search and sort criteria.

@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private double gpa;

@Column(name = "is_full_time")
private boolean isFullTime;

@ManyToOne
@JoinColumn(name = "community_id")
private Community community;

@Column(name = "date_of_birth")
private LocalDate dateOfBirth;

@Column(name = "enrollment_date")
private LocalDate enrollmentDate;

@Column(name = "additional_info")
private String additionalInfo;

private String address;

@Column(unique = true)
private String email;

@Column(name = "first_name")
private String firstName;

@Column(name = "gpa_letter")
private String gpaLetter;

@Column(name = "last_name")
private String lastName;

@Column(name = "phone_number")
private String phoneNumber;
}

This revised documentation provides a clear understanding of how to use GeneralSpecification for dynamic queries in Spring Data JPA.