實際開發中,查詢這一操作是必不可少的。根據多個條件動態查詢的需求是普通的不能再普通的需求了。所以這篇介紹一種根據條件動態查詢的方法。順便介紹下分頁。
在上一篇中,StudentRepository接口繼承了JpaRepository。這種適用於簡單的增刪改查。
現在讓StudentRepository再繼承一個JpaSpecificationExecutor,這樣子就方便我們多種條件的查詢了。
先看下JpaSpecificationExecutor接口的方法
public interface JpaSpecificationExecutor<T> {
T findOne(Specification<T> var1);
List<T> findAll(Specification<T> var1);
Page<T> findAll(Specification<T> var1, Pageable var2);
List<T> findAll(Specification<T> var1, Sort var2);
long count(Specification<T> var1);
}
所有的條件都拼裝成了Specification條件類。
現在StudentRepository的接口是這樣的
public interface StudentRepository extends JpaRepository<Student, Long>, JpaSpecificationExecutor<Student> {
List<Student> findByNameLike(String name);
List<Student> findByAgeGreaterThanAndNameEquals(Integer age, String name);
}
較原來多繼承了一個JpaSpecificationExecutor,下面我們模仿有name值時就根據name模糊查詢,有age值時就查詢等於這個age的值,此處增加兩個類StudentService和StudentServiceImpl
package com.vincent.service;
import com.vincent.model.Student;
import java.util.List;
/**
* @author
* @date 2018/8/21 下午4:27
*/
public interface StudentService {
List<Student> getStudents(String name, Integer age);
}
package com.vincent.service.impl;
import com.vincent.demo.dao.StudentRepository;
import com.vincent.demo.entity.Student;
import com.vincent.demo.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.util.ArrayList;
import java.util.List;
/**
* @author rw
* @date 2019/1/14 下午10:10
*/
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
StudentRepository studentRepository;
@Override
public List<Student> getStudents(String name, Integer age) {
return studentRepository.findAll((Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) -> {
List<Predicate> list = new ArrayList<>();
if (name != null) {
list.add(criteriaBuilder.equal(root.get("name"), name));
}
if (age != null) {
list.add(criteriaBuilder.equal(root.get("age"), age));
}
Predicate[] p = new Predicate[list.size()];
return criteriaBuilder.and(list.toArray(p));
});
}
}
測試
@Test
public void testSelect2() {
System.out.println(studentService.getStudents(null, 12));
System.out.println(studentService.getStudents("a", 12));
}
分頁
接口
Page<Student> getStudents(String name, Integer age, Pageable pageable);
實現
@Override
public Page<Student> getStudents(String name, Integer age, Pageable pageable) {
return studentRepository.findAll((Root<Student> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) -> {
Predicate predicate = null;
if (name != null) {
predicate = criteriaBuilder.equal(root.get("name"), name);
}
if (age != null) {
predicate = criteriaBuilder.equal(root.get("age"), age);
}
return predicate;
}, pageable);
}
測試
@Test
public void testSelect3() {
Page<Student> students = studentService.getStudents(null, null, new PageRequest(0, 2));
System.out.println(students.getContent());
System.out.println(students.getTotalPages());
}
結果
2018-09-05 13:50:15.308 INFO 3953 --- [ main] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
[Student{id=111, name='cba', age=121, schoolId=1}, Student{id=1111, name='vincent', age=22, schoolId=1}]
7
這里有個小注意點,new PageRequest(0, 2)這邊的分頁pageNum是從0開始的,同時pageNum不可以為負數!
