Query by Spec

介紹與使用 Query by Spec (QBS)

Query by Spec (QBS) 提供了 QueryBySpecExecutor<T> 包含了許多查詢方法:

public interface QueryBySpecExecutor<T> { List<T> findBySpec(Object spec); List<T> findBySpec(Object spec, Sort sort); Page<T> findBySpec(Object spec, Pageable pageable); // … more functionality omitted. }

只要在原本的 repository interface 中去繼承 QueryBySpecExecutor<T> 就可以直接使用了:

public interface PersonRepository extends JpaRepository<Person, Long>, QueryBySpecExecutor<Person> { ... } @Service public class PersonService { @Autowired PersonRepository personRepository; public List<Person> findPeople(PersonCriteria criteria) { return personRepository.findBySpec(criteria); } }

Customize Base Repository

在配置的過程中, QBS 會自動配置 Spring Data JPA 的 Base Repository, 預設的實作為 DefaultQueryBySpecExecutor

由於 Java 只能單一繼承, 為了應用程式可以保留原有的 Parent Base Repository, QBS 還多提供了 QueryBySpecExecutorAdapter 擴展點

你的應用程式可以視情況選擇繼承 DefaultQueryBySpecExecutor 或實作 QueryBySpecExecutorAdapter 去客製化 Base Repository, 如:

class MyRepositoryImpl<T, ID> extends SimpleJpaRepository<T, ID> implements QueryBySpecExecutorAdapter<T> { @Setter @Getter private SpecMapper specMapper; private final EntityManager entityManager; MyRepositoryImpl(JpaEntityInformation entityInformation, EntityManager entityManager) { super(entityInformation, entityManager); // Keep the EntityManager around to used from the newly introduced methods. this.entityManager = entityManager; } @Override public Class<T> getDomainClass() { return super.getDomainClass(); } @Transactional public <S extends T> S mySave(S entity) { // implementation goes here } }

並且透過 properties 中的 spec.mapper.repository-base-class 設定成自定義的 base repository 的 fulll package name, 如:

spec: mapper: repository-base-class: com.example.MyRepositoryImpl
Last modified March 24, 2025: docs: add descriptions (ef454a5)