Data JPA
(Spring Boot)
Introduction
n/a
Reference
Spring Data JPA > JPA > JPA Query Methods
https://docs.spring.io/spring-data/jpa/reference/jpa/query-methods.html
Spring Data JPA Query by Example
https://www.baeldung.com/spring-data-query-by-example
pom.xml
<!-- Persist data in SQL stores with Java Persistence API using Spring Data and Hibernate -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Fixes error: jakarta.validation.NoProviderFoundException -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
QueryByExampleExecutor interface
The interface JpaRepository exteds the interface QueryByExampleExecutor:
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T>
The interface QueryByExampleExecutor add more find methods with Example as argument:
<S extends T> Optional<S> findOne(Example<S> example);
<S extends T> Iterable<S> findAll(Example<S> example);
<S extends T> Iterable<S> findAll(Example<S> example, Sort sort);
<S extends T> Page<S> findAll(Example<S> example, Pageable pageable);
<S extends T> long count(Example<S> example);
<S extends T> boolean exists(Example<S> example);
The interface Example provides methods for accessing the probe (instance of our entity) and the ExampleMatcher:
static <T> Example<T> of(T probe)
static <T> Example<T> of(T probe, ExampleMatcher matcher)
T getProbe()
ExampleMatcher getMatcher()
default Class<T> getProbeType()
Note: Our probe and out ExampleMatcher together specify our query.
Limitations
Nesting and grouping statements are not supported, for example: (firstName = ?0 and lastName = ?1) or seatNumber = ?2 (for this, you can use JpaSpecificationExecutor or JPQL)
String matching only includes exact, case-insensitive, starts, ends, contains, and regex
All types other than String are exact-match only
QueryByExampleExecutor examples
Entity:
@Entity
public class Employee {
@Id
@GeneratedValue
private Long id;
private String name;
private String dept;
}
Probe:
Employee employee = new Employee();
employee.setName("Erika");
Example<Employee> employeeExample = Example.of(employee);
Remark: By default, fields having null values are ignored in the underlying query, so above Example will be equivalent to the following JPQL:
SELECT t from Employee t where t.name = 'Erika';
Warning: As Query by Example technique relies on null values to be omitted in the query generation, we should not use primitive identity (like int, long) in our Entity (as in above example) because it will default to 0 instead of null.
findEmployeesByName
System.out.println("-- finding employees with name Tim --");
Employee employee = new Employee();
employee.setName("Tim");
Example<Employee> employeeExample = Example.of(employee);
//calling QueryByExampleExecutor#findAll(Example)
Iterable<Employee> employees = repo.findAll(employeeExample);
findEmployeesByNameAndDept
System.out.println("-- finding employees with name Jack and dept IT --");
Employee employee = new Employee();
employee.setName("Jack");
employee.setDept("IT");
Example<Employee> employeeExample = Example.of(employee);
//calling QueryByExampleExecutor#findAll(Example)
Iterable<Employee> employees = repo.findAll(employeeExample);
Spring Data JPA Projections
Reference article > https://www.baeldung.com/spring-data-jpa-projections
An entity class may have many projections. The reference article demonstrates using repositories with:
Entities
Interface view (closed projection)
Interface view (open projection)
Dto class (projection)
Dynamic( all of the above)