Spring data jpa 查询条件+分页查询
1,依赖

2,application.yml
server:
port: 8082
#数据库连接
spring:
datasource:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/my_test?useUnicode=true&characterEncoding=utf-8
username: root
password: root
#spring-data-jpa,根据实体类生成表
jpa:
hibernate:
ddl-auto: update
show-sql: true
3,实体类,jpa使用实体类生成数据库
@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
@Table(name="student")
public class Student {
@Id
@GeneratedValue
private Integer id;
private String code;
private String name;
private Integer sex;
private Integer age;
@Temporal(TemporalType.DATE)//获取的时候得到yyyy-MM-dd格式日期
private Date birthDate;
}

4, dao
//JpaSpecificationExecutor:自定义条件分页查询
public interface StudentRepository extends JpaRepository<Student,Integer>, JpaSpecificationExecutor<Student> {
// 方式1:方法名称规则查询
Student findByName(String name);
@Query(value = "select * from student where id=?1",nativeQuery=true)
Student findStudentById(int id);
// 方式1:方法名称规则查询
// List<Student> findByNameAndCodeLike(String name, String code);
// 方式2:@Query
//如果当前执行的是一个更新操作时候,还要加上@Modifying注解
//赋值时,默认的情况下,占位符的位置和方法参数位置一致。如果不一致,
//可以使用?+数字 索引的方式,指定占位的取值位置。
@Query(value="select * from student where code like ?2 and name like ?1",nativeQuery=true)
List<Student> findByNameAndCodeLike(String name, String code);
}
5,service
public interface StudentService {
Student saveStu(Student s);
void delStu(Integer id);
Student updateStu(Student s);
Student findStuById(Integer id);
Student findByName(String name);
List<Student> findByNameAndCodeLike(String name ,String code);//模糊查询
Page<Student> findAll(Pageable var2);//分页查询
Page<Student> findAll(Pageable var2,Student s);//分页+条件查询
}
6,serviceImpl
/** * 不带条件的简单分页
* @param p
* @return
*/
@Override
public Page<Student> findAll(Pageable p) {
Page<Student> all = studentRepository.findAll(p);
return all;
}
/** * 方式1
* 动态条件查询+分页
* * @param pageable
* @param s
* @return
*/
@Override
public Page<Student> findAll(Pageable pageable, Student s) {
Page<Student> all = studentRepository.findAll(new Specification<Student>() {
@Override
public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
// Pridicate:表示一个查询条件
List<Predicate> predicates = new ArrayList<Predicate>();//创建一个条件集合
// 获取属性
Path<String> name = root.get("name");
Path<String> code = root.get("code");
// 构造查询条件
Predicate p1 = cb.like(name, "%" + s.getName() + "%");
Predicate p2 = cb.like(code, "%" + s.getCode() + "%");
predicates.add(p1);
predicates.add(p2);
// predicates.add(cb.like(root.get("name"),"%"+s.getName()+"%"));
// predicates.add(cb.like(root.get("code"),"%"+s.getCode()+"%"));
//必须使用toArray(T[])的有参数方法,因为cq.where(p)中的参数的类型必须是Predicate[]数组类型。
//toArray()无参返回的是一个Object类型。
//新建数组方式之一:new A[number]
Predicate[] p = predicates.toArray(new Predicate[predicates.size()]);
cq.where(p);
return null;
}
}, pageable);
return all;
}
/** * 方式2
* @param pageable
* @param s
* @return
*/
// @Override
// public Page<Student> findAll(Pageable pageable, Student s) {
// Page<Student> all = studentRepository.findAll(new Specification<Student>() {
// @Override
// public Predicate toPredicate(Root<Student> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
// Predicate p1 = cb.like(root.get("name"), s.getName());
// Predicate p2 = cb.like(root.get("code"), s.getCode());
// Predicate and = cb.and(p1, p2);
// return and;
// }
// }, pageable);
// return all;
// }
7,controller
@ResponseBody
@GetMapping("findAll")
Page<Student> findAll(@PageableDefault(size = 3) Pageable var2){
Page<Student> all = studentService.findAll(var2);
return all;
}//分页查询
@ResponseBody
@GetMapping("findAllBys")
Page<Student> findAllBys(@PageableDefault(size = 3) Pageable var2,Student s){
s.setName("a");
s.setCode("a");
Page<Student> all = studentService.findAll(var2, s);
return all;
}//分页+条件查询
数据库结果和数据:

条件+分页查询结果:

8,总结:
jpa动态查询主要使用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); //分页查询,Specification:查询条件、Pageable:分页条件
List<T> findAll(Specification<T> var1, Sort var2);//排序
long count(Specification<T> var1);//统计查询
}
Specification接口方法:
public interface Specification<T> {
Predicate toPredicate(Root<T> var1, CriteriaQuery<?> var2, CriteriaBuilder var3);//封装查询条件的方法
}
参数说明:
Specification:表示查询条件,把所有的条件封装到这个对象中,传递到实现JpaSpecificationExecutor对象的方法
做法:自定义我们自己的Specification实现类,实现Specification
Root:查询的根对象(查询的任何属性都可以从根对象中获取),主要获取查询对象属性。
CriteriaQuery:(顶层查询对象,自定义查询方式(不常用)
CriteriaBuilder:查询的构造器,封装了很多的查询条件,如(模糊匹配
equal:直接获取Path对象的属性,然后进行比较即可,但是如:
gt,lt,ge,like等:需要得到path,并指定比较的参数类型:path.as(类型的字节码对象)
@PageableDefault注解,可以看到都有默认值,当然也可覆盖其参数值

方法名称规则查询:
1,findBy+属性名称 :根据属性名称进行查询。
2,fingBy+属性名称+查询方式(Like 或 null 等) :根据属性名称+查询方式进行查询。
3,findBy+属性名称+查询方式+多条件连接符(and 或or 等) +属性名+ 查询方式如:List
findByEmailAddressAndLastname(String emailAddress, String lastname);
分页方式2:利用 PageRequest.of()方法。
@GetMapping("stu/list/{page}/{size}")
public R listStudentPage(@PathVariable("page") int page ,@PathVariable("page") int size ){
if(page<1){
page=1;
}
if(size<=0){
size=10
}
Sort sort = new Sort(Sort.Direction.DESC, "createTime");//排序
Pageable pageable = PageRequest.of(page-1,size,sort);
Page<Student>result = stuDao.findAll(pageable);
return R.data(result);
}
