DEV Community

Salad Lam
Salad Lam

Posted on

Spring Data JPA: About Specification interface

org.springframework.data.jpa.domain.Specification interface

The objective of Specification interface is to let developers make reusable Predicates objects to append into a query when needed.

For example, to create a query of this entity.

@Entity
@Table(name = "Customer")
public class Customer {

    @Id
    @Column(name = "custId")
    private Integer custId;
    @Column(name = "companyName", length = 40, nullable = false)
    private String companyName;
    @Column(name = "contactName", length = 30)
    private String contactName;
    @Column(name = "contactTitle", length = 30)
    private String contactTitle;
    @Column(name = "address", length = 60)
    private String address;
    @Column(name = "city", length = 15)
    private String city;
    @Column(name = "region", length = 15)
    private String region;
    @Column(name = "postalCode", length = 10)
    private String postalCode;
    @Column(name = "country", length = 15)
    private String country;
    @Column(name = "phone", length = 24)
    private String phone;
    @Column(name = "mobile", length = 24)
    private String mobile;
    @Column(name = "email", length = 225)
    private String email;
    @Column(name = "fax", length = 24)
    private String fax;

    // ignore getter and setter
}
Enter fullscreen mode Exit fullscreen mode

In order to pass Specification criteria, please add org.springframework.data.jpa.repository.JpaSpecificationExecutor into the Repository interface.

@Repository
public interface CustomerRepository extends JpaRepository<Customer, Integer>, JpaSpecificationExecutor<Customer> {
}
Enter fullscreen mode Exit fullscreen mode

null Specification

null Specification means no criteria.

customerRepository.findAll((root, query, criteriaBuilder) -> null);
// it is equal to customerRepository.findAll();
Enter fullscreen mode Exit fullscreen mode

To get entities when a field is equal to something

To get entities whose "city" is equal to the value of the String variable "city".

String city;
// ...
Specification<Customer> s = (root, query, criteriaBuilder) -> null;
if (Objects.nonNull(city)) {
    s = s.and((root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("city"), city));
}
customerRepository.findAll(s);
Enter fullscreen mode Exit fullscreen mode

and() This is used for joining two Specification with AND clauses. The other one is or().

Add one more Specification

In addition to "city", "companyName" wants to look up also.

String city;
String companyName;
// ...
Specification<Customer> s = (root, query, criteriaBuilder) -> null;
if (Objects.nonNull(city)) {
    s = s.and((root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("city"), city));
}
if (Objects.nonNull(companyName)) {
    s = s.and((root, query, criteriaBuilder) -> criteriaBuilder.equal(root.get("companyName"), companyName));
}
customerRepository.findAll(s);
Enter fullscreen mode Exit fullscreen mode

Code about can work on cases from no query criteria to with "city" and "companyName" criteria.

Other unnormal usage of Specification interface

You may do following

  • to JOIN other entity
  • to define complex sort if JpaSpecificationExecutor.findAll(Specification , Sort) cannot suit your need

Top comments (0)