This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

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