全面解析JPA 倉庫repository中的findAll()方法
解析JPA倉庫repository的findAll()方法
源碼
Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable);
(1) Specification spec 對象
(2) Pageable pageable 對象
下面是findAll()實現類
public Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable) { //參數spec隻是一個實例,沒有查詢條件 TypedQuery<T> query = getQuery(spec, pageable); return isUnpaged(pageable) ? new PageImpl<T>(query.getResultList()) : readPage(query, getDomainClass(), pageable, spec); }
getQuery(spec,pageable)方法作用
返回一個指定操作表,指定返回項,指定排序方式,指定查詢條件的query對象
1.其中getDomainClass()作用
returns the actual domain class type. 也就是數據表對應的實體類
protected TypedQuery<T> getQuery(@Nullable Specification<T> spec, Pageable pageable) { Sort sort = pageable.isPaged() ? pageable.getSort() : Sort.unsorted(); return getQuery(spec, getDomainClass(), sort); }
2.執行getQuery方法
protected <S extends T> TypedQuery<S> getQuery(@Nullable Specification<S> spec, Class<S> domainClass, Sort sort) { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<S> query = builder.createQuery(domainClass); Root<S> root = applySpecificationToCriteria(spec, domainClass, query); query.select(root); if (sort.isSorted()) { query.orderBy(toOrders(sort, root, builder)); } return applyRepositoryMethodMetadata(em.createQuery(query)); }
其中em是EntityManager對象,用來獲取CriteriaBuilder 實例(參考鏈接CriteriaBuilder動態構造查詢)
CriteriaBuilder
:可以用於創建CriteriaQuery、CriteriaUpdate和CriteriaDelete等createQuery
:hibernate的SQL操作方法,用來生成一個基於 HQL 查詢字符串的 Query 對象,domainClass指的是表對應的實體類
2.1 applySpecificationToCriteria(…)方法:
將Specification中生成的Predicate應用於Criteria
private <S, U extends T> Root<U> applySpecificationToCriteria(@Nullable Specification<U> spec, Class<U> domainClass,CriteriaQuery<S> query) { Assert.notNull(domainClass, "Domain class must not be null!"); Assert.notNull(query, "CriteriaQuery must not be null!"); Root<U> root = query.from(domainClass); if (spec == null) { return root; } CriteriaBuilder builder = em.getCriteriaBuilder(); Predicate predicate = spec.toPredicate(root, query, builder); if (predicate != null) { query.where(predicate); } return root; }
spec.toPredicate(…)方法,是spec實例調用Spec類中的toPredicate(),獲取查詢條件。
where()源碼翻譯:
query.where(predicate)作用,根據predicate(查詢條件的集合)修改query限制查詢結果(如果之前有條件限制,會自動替換),如果此次沒有添加任何限制,之前的條件限制會被移除(也就是說,條件限制會覆蓋),這裡的where()重寫瞭AbstractQuery接口中where(),predicate條件可以為空也可以是多個,返回結果是the modified query
2.2 回到getQuery方法中
query.select(root); if (sort.isSorted()) { query.orderBy(toOrders(sort, root, builder)); }
query.select()
:指定要在查詢結果中返回的項(覆蓋,若之前有所指定,則覆蓋),這裡指定返回項是表對應的實體類,返回結果是the modified queryquery.orderBy()
:修改排序規則,返回結果也是the modified query,這裡不對 toOrders過多的即使
return applyRepositoryMethodMetadata(em.createQuery(query));
em.createQuery(query)
:創建TypedQuery 實例,用來執行executing a criteria query
執行查詢語句,返回結果集(不做詳細分析)
return isUnpaged(pageable) ? new PageImpl<T>(query.getResultList()) : readPage(query, getDomainClass(), pageable, spec);
query.getResultList()
:返回查詢結果(相當於hibernate中list()方法執行hql,返回結果)getResultList()
:方法會調用doList()方法
這個方法中會生成SQL語句expandeQuery:
select generatedAlias0 from Students as generatedAlias0 where 1=1 order by generatedAlias0.studentAge desc
jpa Repository的findOne正確寫法和findAll
@GetMapping("/user/{id}") public User getUser(@PathVariable("id") Integer id) { User user = new User(); user.setId(id); Example<User> example = Example.of(user); Optional<User> one = userRepository.findOne(example); return one.get(); } @GetMapping("/user/all") public List<User> getAll() { List<User> all = userRepository.findAll(); System.out.println(all); return all; }
以上為個人經驗,希望能給大傢一個參考,也希望大傢多多支持WalkonNet。
推薦閱讀:
- jpa EntityManager 復雜查詢實例
- SpringDataJPA詳解增刪改查操作方法
- 使用Spring Data Jpa查詢全部並排序
- Spring Data JPA中 in 條件參數的傳遞方式
- Spring Data Jpa框架最佳實踐示例