Spring 全家桶之 Spring Data JPA(三)

简介: Spring 全家桶之 Spring Data JPA(三)

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

Specifications动态查询方法

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实现类,实现

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

构造查询条件,参数如下bf1d1166f3734924996cec7c5063b871_tplv-k3u1fbpfcp-zoom-in-crop-mark_4536_0_0_0.png

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

动态查询实现

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

findOne(Specification spec)

直接在CustomerDaoTest中书写测试方法

@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匿名内部类,测试结果如下

image.png

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

@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);
}

image.png

findAll(Specification spec)实现模糊查询

/**
 * 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);
    }
}

image.png

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

@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构造排序规则,需要两个参数,排序规则和排序字段,输出结果如下

image.png

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

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

@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);
    }
}

新增分页测试代码

@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);
    }
}

执行分页查询测试成功查出首页数据

image.png


相关文章
|
2月前
|
存储 Java API
如何使用 Java 记录简化 Spring Data 中的数据实体
如何使用 Java 记录简化 Spring Data 中的数据实体
44 9
|
2月前
|
SQL Java 关系型数据库
Springboot引入jpa来管理数据库
Springboot引入jpa来管理数据库
57 0
Springboot引入jpa来管理数据库
|
2月前
|
SQL Java 数据库连接
springBoot+Jpa(hibernate)数据库基本操作
springBoot+Jpa(hibernate)数据库基本操作
70 0
|
3月前
|
Java 数据库连接 API
【Java笔记+踩坑】Spring Data JPA
从常用注解、实体类和各层编写方法入手,详细介绍JPA框架在增删改查等方面的基本用法,以及填充用户名日期、分页查询等高级用法。
|
4月前
|
Java 关系型数据库 MySQL
|
4月前
|
安全 Java 数据安全/隐私保护
基于SpringBoot+Spring Security+Jpa的校园图书管理系统
本文介绍了一个基于SpringBoot、Spring Security和JPA开发的校园图书管理系统,包括系统的核心控制器`LoginController`的代码实现,该控制器处理用户登录、注销、密码更新、角色管理等功能,并提供了系统初始化测试数据的方法。
69 0
基于SpringBoot+Spring Security+Jpa的校园图书管理系统
|
4月前
|
Java Spring 数据库
怎样动动手指就能实现数据操作?Spring Data JPA背后的魔法揭秘
【8月更文挑战第31天】在Java开发中,数据库交互至关重要。传统的JDBC操作繁琐且难维护,而Spring Data JPA作为集成JPA的数据访问层解决方案,提供了CRUD等通用操作接口,显著减少代码量。通过继承`JpaRepository`,开发者能轻松实现数据的增删改查,甚至复杂查询和分页也不再困难。本文将通过示例详细介绍如何利用Spring Data JPA简化数据访问层的开发,提升代码质量和可维护性。
48 0
|
4月前
|
存储 Java 数据库
|
4月前
|
存储 Java API
|
4月前
|
Java 数据库连接 数据库
Spring Data JPA 与 Hibernate 之区别
【8月更文挑战第21天】
102 0