springData Jpa强大的分页功能使用

熟悉Hibernate的人对于ORM给编程带来的便利于快捷一定不陌生,相对于MyBatis等需要编写复杂的SQL语句,ORM映射为我们带来的便利显而易见。但是,在获得便利的同时,失去的便是灵活性。针对初学者来说,要掌握Hibernate灵活的技巧,需要的成本相对较高。在学习Spring Boot时,在数据持久层采用的是Spring Data JPA,对于曾经用过Hibernate的人来说,选择JPA会十分容易上手,因为语法一切都是那么熟悉。但是,在涉及到复杂的查询的时候,尤其是多条件查询的时候,如果通过命名方式实现,长长的方法名将是代码显得十分的不优雅。这个时候,大多数人会选择使用NativeQuery,通过编写SQL语句来实现,这种方式导致的结果就是项目代码中遍地是SQL,随着时间的推移,项目已经失去了使用JPA的初衷。能否有一种方式,在保障JPQL的风格里完成这种复杂的查询呢?这里介绍一种简单的方式:JpaSpecificationExecutor

JpaSpecificationExecutor不属于JpaRepository体系,它允许自定义查询条件实现查询。通过源码可以发现,JpaSpecificationExecutor提供了如下几个方法:
  
  public interface JpaSpecificationExecutor {

T findOne(Specification spec);

List findAll(Specification spec);

Page findAll(Specification spec, Pageable pageable);

List findAll(Specification spec, Sort sort);

long count(Specification spec);
  }

其中,Page findAll(Specification spec, Pageable pageable)是不是看起来很熟悉,因为在JpaRepository我们用的十分常见,只不过这里的入参不同,Pageable提供了排序分页的功能,Specification允许我们自定义查询条件,继续进入源码:

public interface Specification {

Predicate toPredicate(Root root, CriteriaQuery<?> query, CriteriaBuilder cb);

}

没错,这个接口提供了唯一方法toPredicate,通过该方法构造出一个复杂查询条件。Root代表的是实体,CriteriaBuilder是条件构造器,通过该方法,我们构造出复杂的查询条件并返回,JPA便会自动的处理转换查询。下面以一个小demo描述使用

JpaSpecificationExecutor实现复杂查询的步骤:
1、DAO层继承JpaSpecificationExecutor接口(当然,如果需要JpaRepository相关方法,同时继承即可)

@Component
public interface SpeciRepository extends JpaSpecificationExecutor<User>,
JpaRepository<User, Long>{
}

2、Service构造查询条件,并调用DAO层


@Service
@Transactional

public class MySpeciServiceImpl implements MySpeciService {
  
    @Autowired
    private SpeciRepository speciRepository;
 
    @Override
    public Page<User> findByPageAndParams(final User param, int pageNumber, int pageSize) {
    Pageable pageable = new PageRequest(pageNumber, pageSize);  //分页信息
    Specification<User> spec = new Specification<User>() {        //查询条件构造
            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        Path<String> name = root.get("name");
        Path<Integer> age = root.get("age");
        Predicate p1 = cb.like(name, "%" + param.getName() + "%");
        Predicate p2 = cb.lt(age, param.getAge());
           Predicate p = cb.and(p1, p2);         
        return p;   
      }
        };   
    return speciRepository.findAll(spec, pageable);
  }

通过以上两个步骤,就能实现一个基本的复杂分页查询,其实很简单。其中的关键点就是查询条件的构造,可以通过CriteriaBuilder提供的相关谓词进行组装。详细用法这里不累述,有兴趣或有需要可自行baidu。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值