一.排序與分頁
// 排序
Direction direction = Direction.DESC;
//directionStr爲前端傳值,asc代表正序
if ("asc".equals(directionStr)) {
direction = Direction.ASC;
}
//默認使用datetime字段進行排序
String sortProperty = "datetime";
//sortParam爲前端傳的排序字段
if (UtilValidate.isNotEmpty(sortParam)) {
sortProperty = sortParam;
}
Sort sort = new Sort(direction, sortProperty);
// 分頁
// pageNumParam爲頁碼,默認爲0,pageSizeParam爲每頁條數
Pageable pageable = PageRequest.of(pageNumParam, pageSizeParam, sort);
注意:
如果想要按照外鍵關聯實體的某個屬性進行排序,sortProperty直接改爲對應的 “實體名.屬性名” 即可:
1.比如一個User實體對象,外鍵一對一關聯地址實體對象Address,如果希望可以通過地址對象的id字段排序,那麼sortProperty就應該傳 “address.id” 。
@Entity
@Table(name="t_user")
public class User{
@Id
private Long id;
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name = "address_id")
@NotFound(action=NotFoundAction.IGNORE)
private Address address;
/**
* 登錄名
*/
@Column
private String username;
/**
* 狀態
*/
@Column
private Integer state;
/**
* 所屬機構
*/
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name = "department_id")
@NotFound(action=NotFoundAction.IGNORE)
private Department department;
/**
* 註冊時間
*/
@Column
private Long datetime;
}
2.項目使用的是oracle數據庫,使用這種寫法剛開始一直報錯,排查後發現是配置的oracle方言的問題,如果有同樣使用oracle數據庫的小夥伴需要注意下,以下是修改的相關配置項:
#spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.OracleDialect
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.Oracle9Dialect
二.複雜查詢
以下的複雜查詢包含了4種類型:
1.外鍵關聯查詢 — 標註1
2.或查詢 — 標註2
3.外鍵in查詢 — 標註3
4.id的in查詢 — 標註4
使用JPA進行復雜多條件查詢,一般都需要重寫JpaSpecificationExecutor接口中的方法:
public interface JpaSpecificationExecutor<T> {
T findOne(Specification<T> spec);
List<T> findAll(Specification<T> spec);
Page<T> findAll(Specification<T> spec, Pageable pageable);
List<T> findAll(Specification<T> spec, Sort sort);
long count(Specification<T> spec);
}
我們此處需要使用的是Page findAll(Specification spec, Pageable pageable)方法,所以要針對它進行重寫:
// 假設此處查詢的是用戶列表
return userRepository.findAll(new Specification() {
@Override
public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
List<Predicate> pList = new ArrayList<Predicate>();
Predicate[] ps = new Predicate[pList.size()];
List<Predicate> stateList = new ArrayList<Predicate>();
Predicate[] statePs = new Predicate[stateList.size()];
// 查詢用戶表中未刪除的地址 (標註1)
// 假設address是用戶表User中的外鍵關聯,存放地址信息,state爲0代表有效
pList.add(cb.equal(root.join("address").get("state"), 0));
//查詢狀態爲10-未審覈或0-已審覈狀態的用戶 (標註2)
stateList.add(cb.equal(root.get("state"), 0));
stateList.add(cb.equal(root.get("state"),10));
pList.add(cb.or(stateList.toArray(statePs)));
// 時間查詢
pList.add(cb.between(root.get("datetime"), start, end));
// 機構查詢 (標註3)
if (UtilValidate.isNotEmpty(departsStr)) {
Predicate pDepart = inQuery(departsStr, "department", cb, root);
pList.add(pDepart);
}
query.where(pList.toArray(ps));
return null;
}
}, pageable);
以下爲使用到的外鍵關聯in查詢的方法:
public Predicate inQuery(String entityIds, String entityName, CriteriaBuilder cb, Root root) {
List<Predicate> list = new ArrayList<>();
String[] ids = entityIds.split(",");
if (ids != null && ids.length > 0) {
In<Object> in = cb.in(root.join(entityName).get("id"));
for (String id : ids) {
Long idNum = Long.parseLong(id);
in.value(idNum);
}
list.add(in);
}
Predicate[] p = new Predicate[list.size()];
return cb.and(list.toArray(p));
}
如果希望進行id的in查詢,只需把root.join(entityName).get(“id”)改爲root.get(“id”)即可(標註4)。