侧边栏壁纸
博主头像
张种恩的技术小栈博主等级

行动起来,活在当下

  • 累计撰写 748 篇文章
  • 累计创建 65 个标签
  • 累计收到 39 条评论

目 录CONTENT

文章目录

JPA(10)之Spring Data JPA的Specifications动态查询

zze
zze
2019-10-30 / 0 评论 / 0 点赞 / 511 阅读 / 3049 字

有时我们在查询某个实体的时候,给定的条件是不固定的,这时就需要动态构建相应的查询语句,在 Spring Data JPA 中可以通过 JpaSpecificationExecutor 接口查询。相比 JPQL,其优势是类型安全,更加的面向对象,下面是 JpaSpecificationExecutor 中定义的方法:

//根据条件查询一个对象
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);

对于 JpaSpecificationExecutor,这个接口基本是围绕着 Specification 接口来定义的。我们可以简单的理解为,Specification 构造的就是查询条件。
Specification 接口中只定义了如下一个方法:

//构造查询条件
/**
*   root    :Root接口,代表查询的根对象,可以通过root获取实体中的属性
*   query   :代表一个顶层查询对象,用来自定义查询
*   cb      :用来构建查询,此对象里有很多条件方法
**/
public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

使用Specification完成条件查询

//依赖注入customerDao
@Autowired
private CustomerDao customerDao;    
@Test
public void testSpecification() {
    //使用匿名内部类的方式,创建一个Specification的实现类,并实现toPredicate方法
    Specification <Customer> spec = new Specification<Customer>() {
        public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            //cb:构建查询,添加查询方式   like:模糊匹配
            //root:从实体Customer对象中按照custName属性进行查询
            return cb.like(root.get("custName").as(String.class), "ZZ%");
        }
    };
    Customer customer = customerDao.findOne(spec);
    System.out.println(customer);
}

基于Specification的分页查询

//依赖注入customerDao
@Autowired
private CustomerDao customerDao;

@Test
public void testPage() {
    //构造查询条件
    Specification<Customer> spec = new Specification<Customer>() {
        public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            return cb.like(root.get("custName").as(String.class), "ZZ%");
        }
    };

    /**
     * 构造分页参数
     *      Pageable : 接口
     *          PageRequest实现了Pageable接口,调用构造方法的形式构造
     *              第一个参数:页码(从0开始)
     *              第二个参数:每页查询条数
     */
    Pageable pageable = new PageRequest(0, 5);

    /**
     * 分页查询,封装为Spring Data Jpa 内部的page bean
     *      此重载的findAll方法为分页方法需要两个参数
     *          第一个参数:查询条件Specification
     *          第二个参数:分页参数
     */
    Page<Customer> page = customerDao.findAll(spec, pageable);
    System.out.println(page.getContent());
}

对于 Spring Data JPA 中的分页查询,是其内部自动实现的封装过程,返回的是一个 Spring Data
JPA 提供的 pageBean 对象。其中的方法说明如下:

//获取总页数
int getTotalPages();
//获取总记录数   
long getTotalElements();
//获取列表数据
List<T> getContent();
0
JPA

评论区