Spring 全家桶之 Spring Data JPA(三)

2022-08-19 15:30:40 浏览数 (1)

如何在Spring Data JPA中实现动态查询

Specifications动态查询方法

代码语言:javascript复制
T findOne(Specification<T> spec); //查询单个
List<T> findAll(Specification<T> spec); //查询列表
List<T> findAll(Specification<T> spec, Sort sort); //排序查询
Page<T> findAll(Specification<T> spec, Pageable pageable); //分页查询
long count(Specification<T> spec); //统计查询

查询条件-Specification

自定义Specification实现类,实现

代码语言:javascript复制
Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb);

构造查询条件,参数如下

  • Root:查询的对象,查询条件/属性都可以从root对象中获取
  • CriteriaQuery:上层查询对象,定义查询方式,一般不用
  • CriteriaQueryBuilder:查询对象的构造器,封装了较多的查询条件

动态查询实现

1.新建Maven项目,加入Maven依赖 2.新建entity包,增加实体类Customer 3.新建dao包,增加CustomerDao 4.在test包中新建dao包,增加CustomerDao

findOne(Specification spec)

直接在CustomerDaoTest中书写测试方法

代码语言:javascript复制
@Test
public void testFindOne(){
    // 匿名内部类
    Specification<Customer> specification = (Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
        // 构造查询条件,实现toPredicate方法
        //1.获取比较的属性
        Path<Object> custName = root.get("custName");
        //2.构造查询条件,equal为精准匹配
        Predicate thor_odin = cb.equal(custName, "Thor Odin");
        return thor_odin;
    };

    Customer one = customerDao.findOne(specification);
    System.out.println(one);
}

使用了lambda表达式实现Specification匿名内部类,测试结果如下

多个条件查询,使用and或者or连接多个查询条件

代码语言:javascript复制
@Test
public void testFindOneByMultiCondition(){
    Specification<Customer> specification = (Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
        // 构造查询条件,实现toPredicate方法
        //1.获取比较的属性
        Path<Object> custName = root.get("custName");
        Path<Object> custIndustry = root.get("custIndustry");
        //2.构造查询条件,equal为精准匹配
        Predicate thor_odin = cb.equal(custName,"Thor Odin");
        Predicate asgard = cb.equal(custIndustry, "God of Thunder");
        // 组合查询条件,以与的形式组合查询条件,也可以使用or
        Predicate mutil = cb.and(thor_odin, asgard);
        return mutil;
    };

    Customer one = customerDao.findOne(specification);
    System.out.println(one);
}

findAll(Specification spec)实现模糊查询

代码语言:javascript复制
/**
 * equal方法可以直接使用path属性及属性值的方式得到Predicate对象
 * gt,lt,ge,le,like需要使用path属性.as(属性类型.class)及属性vlaue来得到Predicate对象
 */
@Test
public void testFindAllByLike(){
    Specification<Customer> specification = (Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
        // 构造查询条件,实现toPredicate方法
        //1.获取比较的属性
        Path<Object> custSource = root.get("custSource");

        Predicate like = cb.like(custSource.as(String.class), "FB%");
        return like;
    };

    List<Customer> all = customerDao.findAll(specification);
    for (Customer customer : all) {
        System.out.println(customer);
    }
}

List findAll(Specification spec, Sort sort); 排序查询

代码语言:javascript复制
    @Test
    public void testFindAllByLikeAsc(){
        Specification<Customer> specification = (Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) -> {
            // 构造查询条件,实现toPredicate方法
            //1.获取比较的属性
            Path<Object> custSource = root.get("custSource");

            Predicate like = cb.like(custSource.as(String.class), "FB%");
            return like;
        };

        // 排序规则,倒叙排列
        Sort sort = new Sort(Sort.Direction.DESC,"custId");


        List<Customer> all = customerDao.findAll(specification,sort);
        for (Customer customer : all) {
            System.out.println(customer);
        }
    }
}

使用Sort构造排序规则,需要两个参数,排序规则和排序字段,输出结果如下

Page findAll(Specification spec, Pageable pageable)分页查询

先通过save()方法往表中添加数据

代码语言:javascript复制
@Test
public void testInsert(){
    for (int i = 1; i <= 30; i  ) {
        Customer customer = new Customer();
        customer.setCustName("Spider Army No "   i);
        customer.setCustIndustry("Queen");
        customer.setCustLevel("LV 1");
        customerDao.save(customer);
    }
}

新增分页测试代码

代码语言:javascript复制
@Test
public void testPaging(){
    Specification spec = null;
    // 当前查询页数和每页查询数量
    Pageable pageable = new PageRequest(0,5);
    Page<Customer> all = customerDao.findAll(null,pageable);
    //获取总页数
    System.out.println(all.getTotalPages());
    // 获取数据总量
    System.out.println(all.getTotalElements());
    // 获取当前页数据集合
    List<Customer> content = all.getContent();
    // 遍历集合,得到当前页的所有Customer数据
    for (Customer customer : content) {
        System.out.println(customer);
    }
}

执行分页查询测试

成功查出首页数据

0 人点赞