Specification & Predicate: Advance Search and Filtering in JPA

This article is all about Understanding the Specification and Predicate Methods of a JPA Query. JPA stands for Java Persistence API and indicates a standard API which has been developed for persisting Java Objects into a database. JPA specifies several query language which you can use to query the database. The most popular language is the JPQL. (Note: This blog has not yet been published, it is a draft) 6.  Find a blog for a different demographic to you that relates to your blog’s theme.  7.  Find at least 10 blogs that are part of your different demographic.  8.  For each of the 10 blogs you have found, find at least 3 possible guest post opportunities.

The most amazing thing about computers is that they can do a lot of things. But there is a downside to this: it’s a lot of hassle to create the programs that make computers do what we want. This doesn’t only apply to generic computer users, but also to programmers, who have to spend a lot of time learning the computer language they want to use, and then writing a lot of code. For this reason, it would be great if there were a way to just give the computer a description of what we want it to do, and then have it do it for us.

JPQL is the language used to make queries to your database allowing you to retrieve data from it. The interesting thing about JPQL is that it can handle both simple and complex queries allowing you to retrieve only the data that you need. This article will be about how to make simple and complex queries using this powerful language.

In this lesson, you will learn how to use the specification and predicate in Spring Data JPA using the Spring Boot RESTful API project. The Spring Data JPA specification allows us to create dynamic database queries using the JPA criteria API. It defines a specification as a predicate on an entity. Spring has a wrapper around the JPA Criteria API (which uses predicates) called the Specification API. The Spring Data JPA repository abstraction allows predicates to be performed through the JPA Criteria API predicates wrapped in a specification object. To enable this feature, you must allow your repository to extend the JpaSpecificationExecutor. In the following example, I explain step by step how to implement the specification and predicate in a RESTful API project. I have created a database called jp_database. In this database, I created a table called jp_users.

MySQL database and table

word-image-3789 word-image-3790

Creating an application

Let’s start by creating a simple Spring Boot application using Spring Data JPA and a MySQL database. I have created 3 projects based on Maven modules with the following project hierarchy:

  • Iats-jp-api
  • Iats-jp-core
  • Iats-jp-parent

In the API project, I created a controller class with all the methods like GET, POST, PUT DELETE and so on. The kernel project contains all the business logic, and the parent project contains both the API and the kernel modules. word-image-3791 word-image-3792 In our application, there is only one user entity class, as shown below: import java.util.Date ; import javax.persistence.Column ; import javax.persistence.Entity ; import javax.persistence.GeneratedValue ; import javax.persistence.GenerationType ; import javax.persistence.Id.Table ; import javax.persistence.Temporal ; import javax.persistence.TemporalType ; import org.hibernate.annotations.Formula ; @EntityId.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.hibernate.annotations.Formula; @Entity @Table(name = jp_users) public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = user_id) private Integer userId; @Column(name = email) private String email; @Column(name = password) private String password; @Column(name = first name) private String first name; @Column(name = middle_name) private String middle_name ; @Column(name = last_name) private String last_name; @Compound(concat(firstname, middle_name, last_name)) private String full name; @Column(name = gender) private String gender; @Column(name = date of birth) @Temporal(TemporalType.DATE) private Date birthDate; @Column(name = phone_number) private String phNumber; @Column(name = summary) private String summary; @Column(name = experience) private Integer experience; @Column(name = profile_img) private String profImg; @Column(name = current_salary) private double currSalary ; @Column(name = expected_salary) private double exptSalary ; @Column(name = is_enable) private Integer isEnalbe ; @Column(name = role_id) private Integer roleId ; @Column(name = company_id) private Integer compId; @Column(name = is_owner) private Integer isOwner; public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getMiddleName() { return middleName; } public void setMiddleName(String middleName) { this.middleName = middleName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public String getGender() { return gender; } public void setGender(String gender) { this.gender = gender; } public Date getBirthDate() { return birthDate; } public void setBirthDate(Date birthDate) { this.birthDate = birthDate; } public String getPhNumber() { return phNumber; } public void setPhNumber(String phNumber) { this.phNumber = phNumber; } public String getSummary() { return summary; } public void setSummary(String summary) { this.Summary = summary; } public Integer getExperience() { return experience; } public void setExperience(Integer experience) { this.experience = experience; } public String getProfImg() { return profImg; } public void setProfImg(String profImg) { this.profImg = profImg ; } public double getCurrSalary() { return currSalary ; } public void setCurrSalary(double currSalary) { this.currSalary = currSalary; } public double getExptSalary() { return exptSalary; } public void setExptSalary(double exptSalary) { this.exptSalary = exptSalary; } public Integer getIsEnalbe() { return isEnalbe; } public void setIsEnalbe(Integer isEnalbe) { this.isEnalbe = isEnalbe; } public Integer getRoleId() { return roleId; } public void setRoleId(Integer roleId) { this.roleId = roleId; } public Integer getCompId() { return compId; } public void setCompId(Integer compId) { this.compId = compId; } public Integer getIsOwner() { return isOwner; } public void setIsOwner(Integer isOwner) { this.isOwner = isOwner; } public String getFullName() { return fullName; } public void setFullName(String fullName) { this.fullName = fullName; } The next step is to create an interface for the repository, called UserRepository, to retrieve data from the database. To use the specification, we also need to extend our repository interface with the JpaSpecificationExecutor interface. This interface provides methods for implementing the specifications. Here is what the interface of our archive looks like: import java.util.List; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; import org.springframework.stereotype.Repository; import com.iats.entity.User; @Repository public interface UserRepository extends JpaRepository, JpaSpecificationExecutor { public page findAll(Specification spec, Pageable pageable); public list findAll(Specification spec); }

Preparation of specifications

Let’s move on to the most interesting part of the article: creating specifications for running dynamic queries to find users in the database. Create a UserSpecification class and provide an implementation of the getUsers method: import java.util.ArrayList; import java.util.List; import javax.persistence.criteria.Predicate; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Component; import com.iats.entity.User; import com.iats.model.request.UserRequest; @Component public class UserSpecification { public Specification getUsers(UserRequest request) { return(root, query, criteriaBuilder) -> { List predicates = new ArrayList<>(); if (request.getEmail() != null && !request.getEmail().isEmpty()) { predicates.add(criteriaBuilder.equal(root.get(email), request.getEmail()); } if (request.getName() != null && !request.getName().isEmpty()) { predicates.add(criteriaBuilder.like(criteriaBuilder.lower(root.get(fullName)))), % + request.getName().toLowerCase() + %)); } if (request.getGender() != null && !request.getGender().isEmpty()) { predicates.add(criteriaBuilder.equal(root.get(gender)), request.getGender()); } query.orderBy(criteriaBuilder.desc(root.get(experience)); return criteriaBuilder.and(predicates.toArray(new Predicate[0]); } You can use the UserSpecification class to combine multiple specifications to filter users based on multiple constraints. With this class you can easily make different types of database queries dynamic. The UserSpecification class filters users by email, name (a full name consisting of a first, middle and last name) and gender using a specification and a predicate.

UserService interface and implementation of the UserServiceImpl class

User Service Interface import com.iats.model.request.UserRequest; import com.iats.model.response.UserResponseList; public interface UserService { public UserResponseList getUserList(UserRequest userRequest); } UserServiceImpl class import java.util.ArrayList ; import java.util.List ; import org.springframework.beans.factory.annotation.Autowired ; import org.springframework.beans.factory.annotation.Value ; import org.springframework.data.domain.Page ; import org.springframework.data.domain.PageImpl; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import com.iats.entity.User; import com.iats.model.request.UserRequest; import com.iats.model.response.UserResponseDto; import com.iats.model.response.UserResponseList; import com.iats.repository.UserRepository; import com.iats.service.UserService; import com.iats.specification.UserSpecification; @Service public class UserServiceImple implements UserService { @Autowired private UserRepository userRepository; @Autowired private UserSpecification userSpecification; @Value(${pagination.page.size.default}) private Integer defaultPageSize; @Override public UserResponseList getUserList(UserRequest request) { List list = null; Page pages = null; if (request.getPageNumber() == null) { pages = new PageImpl<>(userRepository.findAll(userSpecification.getUsers(request)); } else { if (request.getPageSize() == null) { request.setPageSize(defaultPageSize); } } Pageable paging = PageRequest.of(request.getPageNumber() – 1, request.getPageSize()); pages = userRepository.findAll(userSpecification.getUsers(request), paging); } if (pages != null && pages.getContent() != null) { list = pages.getContent(); if (list != null && list.size() > 0) { UserResponseList respList = new UserResponseList(); respList.setTotalPages(pages.getTotalPages()); respList.setTotalCount(pages.getTotalElements()); respList.setPageNo(pages.getNumber() + 1); respList.setUsers(new ArrayList()); for (User users : list) { UserResponseDto obj = new UserResponseDto(); obj.populateObject(users); respList.getUsers().add(obj); } return respList; } } return null; } User controller class that calls the getUserList method in the UserServiceImpl class. import javax.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.iats.constant.Constant; import com.iats.model.request.UserRequest; import com.iats.model.response.UserResponse; import com.iats.model.response.UserResponseList; import com.iats.service.UserService; @RestController @RequestMapping(value = /api/v1) public class UserController { @Autowired private UserService userService; @PostMapping(/getUsers) public ResponseEntity getUsersList(@Valid @RequestBody UserRequest request) { UserResponse response = new UserResponse(Constant.STATUS_TRUE, Constant.SUCCESS); UserResponseList obj = userService.getUserList(request); response.setData(obj); return ResponseEntity.ok(response); }. } Test the application: Using Postman, we will test the RESTful API POST method to retrieve users based on various filter parameters. In the database, I have 3 records. word-image-3793 Here is a postman HTTP request to retrieve records from the database based on filter parameters. In the first example, I pass the body of the request with the email address, name, and gender. The data is displayed according to the parameters.

Test case 1

word-image-3794 word-image-3795 In the second example, I only pass a name parameter and the data is displayed according to the name filter parameter. This name parameter can be a first, middle or last name and is looked up using the name key.

Test case 2

word-image-3796 word-image-3797 In the above example, two records are displayed based on the name key. It looks for the key there in the columns of the database (first name, middle name and last name) and, if found, prints the data in the answer. The entire search was conducted with Specification and Predicate. Synopsis: In this tutorial, you learned how to use Spring Data Specifications and Predicates with the JPA Criteria API to dynamically generate database queries. The specification provides us with a robust and flexible approach to building database queries to handle complex use cases. This guide covers the basic operations that can be used to implement a powerful search function.In this blog we will be discussing the advantages of using the JPA specification and the Predicate. While the JPA specification is not a form of search and filtering mechanism available in the JPA specification, it is an integral part of the JPA specification that is used to interact with the database and retrieve the results. Further, the Predicate are used in conjunction with the Specification and JPA to create complex queries.. Read more about specification in tagalog and let us know what you think.

Frequently Asked Questions

What is called specification?

The term specification can be used to refer to the description of the hardware, software or the functional requirements of a product. Specification can mean the set of characteristics of a product that will satisfy customer requirements and can be used to make product decisions. Software and Hardware Requirements Specifications (SRSs) are used for various purposes. The primary objective of SRSs is to describe requirements in sufficient detail to allow a system to be implemented. In many cases, such specifications are also used by a customer to evaluate competing products. In software development, the term specification has multiple meanings. Specifications may be literal or abstract.

What are the types of specification?

Types of specification are important to understand, regardless of the technology stack you are working with. The two main variants are the functional and non-functional specifications. The former is the type of specification that is aimed at describing the functionality of the system under development. Such specification contains information regarding the system’s inputs, outputs, operation and the like. On the other hand, non-functional specifications are those that describe the non-functional aspects of the system. Such aspects may include performance, scalability and maintainability of the system. Specifications are very important in the electronics industry since they are the rules that designers must follow when they design a new device. The specification that is most important is the specification of the individual components that are used in a device. The reason for this importance is that the specification of the components is the basis of how the device will behave and work.

What is another word for specifications?

I just got my hands on the latest flagship iPhone. The screen is amazing, the processor is lightning fast and the camera is so good I can take pictures on Mars and they’ll look as if they were taken on Earth. But the hardware specifications aren’t the only thing that makes this phone great. The operating system is intuitive and easy to use. The software is so streamlined that it’s so simple to install software updates. As we all know, specifications are a set of detailed requirements for something. In the technology world, specifications are often used to specify the performance, quality, or characteristics of a product or service or of various components. A simple example is a specification for a screw. A screw specification can include information such as the type of metal, the shape, and the length. It can also include tolerances about the length and the diameter.

Related Tags:

Feedback,specification synonymspecification biologytypes of specificationsspecification in constructionwhat is specification in procurementtechnical specification,People also search for,Privacy settings,How Search works,Obligation,Resolution,Missive letter,Letter,Clause,Specification by example,Specification example,types of specifications,specification in construction,specification definition engineering,specification in tagalog,what is specification in procurement,specification biology,standard specification

Leave a Reply

Your email address will not be published. Required fields are marked *