Spring Data JPA複雜查詢
在使用Spring Data JPA框架時,可以按照符合框架規則的自定義方法或@Query
進行固定條件查詢。如果是動態條件查詢框架也提供了介面。
public interface JpaSpecificationExecutor<T>
1.符合框架規則的自定義方法:
Keyword | Sample | JPQL snippet |
---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2.@Query
查詢:
@Modifying
@Transactional
@Query("DELETE FROM UnitRevocationRecord WHERE rid in (:ids)")
void deleteUnitRevocationRecordByIds(@Param("ids") List<String> ids);
3.JpaSpecificationExecutor
複雜查詢
這個介面的使用和其它介面一樣,在你的Dao介面繼承即可。
public interface UnitRevocationDao extends PagingAndSortingRepository <UnitRevocationRecord, String>, JpaSpecificationExecutor<UnitRevocationRecord> {}
JpaSpecificationExecutor
介面提供了很多的條件查詢的介面:
/**
* Interface to allow execution of {@link Specification}s based on the JPA criteria API.
*
* @author Oliver Gierke
*/
public interface JpaSpecificationExecutor<T> {
/**
* Returns a single entity matching the given {@link Specification}.
*
* @param spec
* @return
*/
T findOne(Specification<T> spec);
/**
* Returns all entities matching the given {@link Specification}.
*
* @param spec
* @return
*/
List<T> findAll(Specification<T> spec);
/**
* Returns a {@link Page} of entities matching the given {@link Specification}.
*
* @param spec
* @param pageable
* @return
*/
Page<T> findAll(Specification<T> spec, Pageable pageable);
/**
* Returns all entities matching the given {@link Specification} and {@link Sort}.
*
* @param spec
* @param sort
* @return
*/
List<T> findAll(Specification<T> spec, Sort sort);
/**
* Returns the number of instances that the given {@link Specification} will return.
*
* @param spec the {@link Specification} to count instances for
* @return the number of instances
*/
long count(Specification<T> spec);
}
在這些方法中,可以看到查詢需要Specification
型別的引數
/**
* Specification in the sense of Domain Driven Design.
*
* @author Oliver Gierke
* @author Thomas Darimont
* @author Krzysztof Rzymkowski
*/
public interface Specification<T> {
/**
* Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
* {@link Root} and {@link CriteriaQuery}.
*
* @param root
* @param query
* @return a {@link Predicate}, may be {@literal null}.
*/
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);
}
root引數用來對應實體的資訊的。criteriaBuilder可以幫助我們製作查詢資訊,它提供了很多的方法:大於,小於,等於等。如果有多個條件,我們就可以建立一個Predicate集合,最後用CriteriaBuilder的and和or方法進行組合,得到最後的Predicate物件。
示例程式碼:
public PageQueryData<UnitRevocationListDto> queryUnitRevocationRecord(PageQueryData <UnitRevocationListDto> pageQueryData, Integer queryType) {
String userId = WebServiceUtils.getCurrentUserId();
Pageable pageable = new PageRequest(pageQueryData.getPage() - 1,pageQueryData.getRows());
// 查詢條件
Map <String, String> searchTexts = pageQueryData.getSearchTexts();
// 條件分頁功能
Page <UnitRevocationRecord> pages = unitRevocationDao.findAll((root, query, cb) -> {
List<Predicate> lstPredicates = new ArrayList <>();
if(searchTexts != null){
if(!CheckUtil.isNullorEmpty(searchTexts.get("unitId"))){
lstPredicates.add(cb.equal(root.get("unitId"),searchTexts.get("unitId")));
}
if(!CheckUtil.isNullorEmpty(searchTexts.get("applicantId"))){
lstPredicates.add(cb.equal(root.get("applicantId"),searchTexts.get("applyUnitId")));
}
if(!CheckUtil.isNullorEmpty(searchTexts.get("state"))){
lstPredicates.add(cb.equal(root.get("state"),searchTexts.get("state")));
}
}
if(queryType == 0){
lstPredicates.add(cb.equal(root.get("applicantId"),userId));
}else if(queryType == 1){
lstPredicates.add(cb.notEqual(root.get("state"),EnumUnitRevocationState.NREPORT.getState()));
lstPredicates.add(cb.notEqual(root.get("state"),EnumUnitRevocationState.CALLBACK.getState()));
}
Predicate[] arrayPredicates = new Predicate[lstPredicates.size()];
return cb.and(lstPredicates.toArray(arrayPredicates));
}, pageable);
List <UnitRevocationRecord> content = pages.getContent();
List <UnitRevocationListDto> records = new ArrayList <>();
content.forEach(item -> {
UnitRevocationListDto unitRevocationListDto = this.convertRevocation(queryType, item);
records.add(unitRevocationListDto);
});
pageQueryData.setTotal((int) pages.getTotalElements());
pageQueryData.setQueryList(records);
return pageQueryData;
}