Spring data jpa 查询条件+分页查询

本文介绍了如何在Spring Data JPA中实现动态查询和分页查询。通过依赖设置、配置、实体类、DAO、Service、ServiceImpl和Controller的步骤,展示了条件查询与分页查询的具体实现。重点讲解了JpaSpecificationExecutor接口和Specification接口的使用,以及自定义Specification实现类。同时,提到了Root对象、CriteriaQuery和CriteriaBuilder在构建查询条件中的作用,以及PageableDefault注解和PageRequest.of()方法在分页查询中的应用。

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<T>接口里面的方法和Specification接口。

JpaSpecificationExecutor<T>接口方法:

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<User> findByEmailAddressAndLastname(String emailAddress, String lastname);

更多查看:https://docs.spring.io/spring-data/jpa/docs/2.3.0.RELEASE/reference/html/#jpa.query-methods.named-queries
 

 

分页方式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);
	
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值