SpringDataJPA - 3:动态查询(Specifications)

@TOC~~~java
DAO接口继承的接口中有一个接口:JpaSpecificationExecutor,在这个接口中有几个关键方法和对象对象:
public void specTest3() {
// 构造查询条件,null表示无条件
Specification spec = null;
// 构造分页对象,当前第一页,每页2条
Pageable pageable = PageRequest.of(0, 2);
// 执行查询操作
Page page = dao.findAll(spec, pageable);

    System.out.println(page.getContent()); // 当前页数据
    System.out.println(page.getTotalElements()); // 总条数
    System.out.println(page.getTotalPages()); // 总页数
}

**`Sort`:排序对象**

构造排序对象,使用静态方法 `Sort.by(Sort.Direction,String... properties)` 
第一个参数:`Direction`
* Sort.Direction.DESC 降序
* Sort.Direction.ASC 升序

第二个参数:`properties` 需要排序的属性名称

```java

    // sql: select * from user_demo where user_age <> 0 order by user_age desc
    
    @Test
    public void specTest2() {
        Specification<UserDemo> spec = new Specification<UserDemo>() {
            @Override
            public Predicate toPredicate(Root<UserDemo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Object> userAge = root.get("userAge");
                return criteriaBuilder.notEqual(userAge, 0);
            }
        };
        Sort sort = Sort.by(Sort.Direction.DESC, "userAge");
        List<UserDemo> list = dao.findAll(spec, sort);
        for (UserDemo userDemo : list) {
            System.out.println(userDemo);
        }
    }


DAO接口继承的接口中有一个接口:`JpaSpecificationExecutor`,在这个接口中有几个关键方法和对象对象:
**方法**

```java
    // 查询单条
    Optional<T> findOne(@Nullable Specification<T> var1);
    
    // 查询所有
    List<T> findAll(@Nullable Specification<T> var1);

    // 查询所有,返回分页
    Page<T> findAll(@Nullable Specification<T> var1, Pageable var2);

    // 按照排序规则返回所有
    List<T> findAll(@Nullable Specification<T> var1, Sort var2);

    // 统计
    long count(@Nullable Specification<T> var1);
```

**对象**
`Specification`:查询条件对象

在实现的的时候需要实现其中一个方法:`toPredicate`,其中有三个参数:`root`、`criteriaQuery`、`criteriaBuilder`

- root:查询的根对象(查询任何属性都可以从根对象中获取,方法`get(String name)`,这里的name指的是数据库字段对应的属性名,并非数据库字段名称)
- criteriaQuery:顶层查询对象,自定义查询方式(一般不用)
- criteriaBuilder:查询的构造器,内部封装了很多查询条件

```java
    @Test
    public void specTest1() {
        /*
        匿名内部类,自定义查询条件
            1、实现 Specification 接口,提供泛型(查询的对象类型)
            2、实现 toPredicate 方法(构造查询条件)
                参数1:root - 获取需要查询的对象属性
                参数2:criteriaQuery - ?
                参数3:criteriaBuilder - 构造查询条件,内部封装了很多查询条件(例如模糊匹配,精准匹配)
            sql:select * from user_demo where user_name = '张三' and user_age = 20
         */
        Specification<UserDemo> specification = new Specification<UserDemo>() {
            @Override
            public Predicate toPredicate(Root<UserDemo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                // 1.获取比较的属性
                Path<Object> userName = root.get("userName");
                Path<Object> userAge = root.get("userAge");
                // 2.构造查询条件执行并返回
                Predicate p1 = criteriaBuilder.equal(userName, "张三");
                Predicate p2 = criteriaBuilder.equal(userAge, 20);
                // 3.将多个条件联系起来
                return criteriaBuilder.and(p1, p2);
            }
        };
        System.out.println(dao.findOne(specification));
    }
```

**`criteriaBuilder`常用构造条件:**

```
between:between and
equal:相等 =
like:like
eq:equal(相等)
ne:not equal(不等)
gt:greater than(大于)
ge:greater than or equal(大于或等于)
lt:less than(小于)
le:less than or equal(小于或等于)
```

- `equal`:直接得到Path对象,然后进行比较

```java
Path<Object> userName = root.get("userName");
Predicate p = criteriaBuilder.equal(userName, "张三");
```

- `gt,ge,lt,le,like`:得到path对象,根据Path指定参数类型(path.as(class))字节码进行比较

```java
Path<Object> userName = root.get("userName");
Predicate p = criteriaBuilder.like(userName.as(String.class), "%张三%");
```

**`Pageable`:分页对象**

spring data jpa 中提供了1个分页查询方法:

```
Page<T> findAll(@Nullable Specification<T> var1, Pageable var2);
```

`@Nullable` 表示参数var1可以传入null
`Pageable`对象是一个接口,实现类为:org.springframework.data.domain.PageRequest,可以调用静态方法`PageRequest.of(int page, int size)`进行实例化,page表示当前页,从0开始,size表示每页查询数量

```java
    @Test
    public void specTest3() {
        // 构造查询条件,null表示无条件
        Specification<UserDemo> spec = null;
        // 构造分页对象,当前第一页,每页2条
        Pageable pageable = PageRequest.of(0, 2);
        // 执行查询操作
        Page<UserDemo> page = dao.findAll(spec, pageable);

        System.out.println(page.getContent()); // 当前页数据
        System.out.println(page.getTotalElements()); // 总条数
        System.out.println(page.getTotalPages()); // 总页数
    }
```

**`Sort`:排序对象**

构造排序对象,使用静态方法 `Sort.by(Sort.Direction,String... properties)`
第一个参数:`Direction`

- Sort.Direction.DESC 降序
- Sort.Direction.ASC 升序

第二个参数:`properties` 需要排序的属性名称

```java
    // sql: select * from user_demo where user_age <> 0 order by user_age desc
    
    @Test
    public void specTest2() {
        Specification<UserDemo> spec = new Specification<UserDemo>() {
            @Override
            public Predicate toPredicate(Root<UserDemo> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Object> userAge = root.get("userAge");
                return criteriaBuilder.notEqual(userAge, 0);
            }
        };
        Sort sort = Sort.by(Sort.Direction.DESC, "userAge");
        List<UserDemo> list = dao.findAll(spec, sort);
        for (UserDemo userDemo : list) {
            System.out.println(userDemo);
        }
    }
```
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值