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

1.对于JpaSpecificationExecutor,这个接口基本是围绕着Specification接口来定义的。我们可以简单的理解为,Specification构造的就是查询条件。

Specification接口中只定义了如下一个方法:

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

1.通过单个条件查询对象

  1. /**
  2. * 根据条件查询单个对象
  3. */
  4. @Test
  5. public void testFindOne() {
  6. //匿名内部类
  7. /**
  8. * 自定义查询条件
  9. * 1.实现Specification接口(提供泛型:查询的对象类型)
  10. * 2.实现toPredicate方法(构造查询条件)
  11. * 3.需要借助方法参数中的两个参数(
  12. * root:获取需要查询的对象属性
  13. * CriteriaBuilder:构造查询条件的,内部封装了很多的查询条件(模糊匹配,精准匹配)
  14. * )
  15. * 案例:根据客户名称查询,查询客户名为传智播客的客户
  16. * 查询条件
  17. * 1.查询方式
  18. * cb对象
  19. * 2.比较的属性名称 实体类名称
  20. * root对象
  21. *
  22. */
  23. Specification<Customer> spec = new Specification<Customer>() {
  24.  
  25. @Override
  26. public Predicate toPredicate(Root root, CriteriaQuery query, CriteriaBuilder cb) {
  27. //1.获取比较的属性
  28. Path<Object> custName = root.get("custName");
  29. //2.构造查询条件 : select * from cst_customer where cust_name = 'hdh'
  30. Predicate predicate = cb.equal(custName, "hdh");//进行精准的匹配 (比较的属性,比较的属性的取值)
  31. return predicate;
  32. }
  33. };
  34. Customer customer = customerSpecDao.findOne(spec);
  35. System.out.println(customer);
  36. }

2.通过多个字段条件查询对象

  1. /**
  2. * 多条件查询
  3. * 案例:根据客户名(传智播客)和客户所属行业查询(it教育)
  4. *
  5. */
  6. @Test
  7. public void testSpec1() {
  8. /**
  9. * root:获取属性 实体类名称
  10. * 客户名
  11. * 所属行业
  12. * cb:构造查询
  13. * 1.构造客户名的精准匹配查询
  14. * 2.构造所属行业的精准匹配查询
  15. * 3.将以上两个查询联系起来
  16. */
  17. Specification<Customer> spec = new Specification<Customer>() {
  18. @Override
  19. public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  20.  
  21. Path<Object> p1 = root.get("custName");
  22. Path<Object> p2 = root.get("custIndustry");
  23. Predicate custName = cb.equal(p1, "hdh");
  24. Predicate custIndustry = cb.equal(p2, "it");
  25.  
  26. Predicate equal = cb.and(custName, custIndustry);
  27. return equal;
  28. }
  29. };
  30. Customer customer = customerSpecDao.findOne(spec);
  31. System.out.println(customer);
  32. }

3.模糊排序查询

  1. /**
  2. * 案例:完成根据客户名称的模糊匹配,返回客户列表
  3. * 客户名称以 ’h‘ 开头
  4. *
  5. * equal :直接的到path对象(属性),然后进行比较即可
  6. * gt,lt,ge,le,like : 得到path对象,根据path指定比较的参数类型,再去进行比较
  7. * 指定参数类型:path.as(类型的字节码对象)
  8. */
  9. @Test
  10. public void testSpec3() {
  11. //构造查询条件
  12. Specification<Customer> spec = new Specification<Customer>() {
  13. @Override
  14. public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
  15. //查询属性:客户名
  16. Path<Object> custName = root.get("custName");
  17. //查询方式:模糊匹配
  18. Predicate like = cb.like(custName.as(String.class), "h%");
  19. return like;
  20. }
  21. };
  22. // List<Customer> list = customerDao.findAll(spec);
  23. // for (Customer customer : list) {
  24. // System.out.println(customer);
  25. // }
  26. //添加排序
  27. //创建排序对象,需要调用构造方法实例化sort对象
  28. //第一个参数:排序的顺序(倒序,正序)
  29. // Sort.Direction.DESC:倒序
  30. // Sort.Direction.ASC : 升序
  31. //第二个参数:排序的属性名称
  32. Sort sort = new Sort(Sort.Direction.DESC,"custId");
  33. List<Customer> list = customerSpecDao.findAll(spec, sort);
  34. for (Customer customer : list) {
  35. System.out.println(customer);
  36. }
  37. }

4.分页查询

  1. /**
  2. * 分页查询
  3. * Specification: 查询条件
  4. * Pageable:分页参数
  5. * 分页参数:查询的页码,每页查询的条数
  6. * findAll(Specification,Pageable):带有条件的分页
  7. * findAll(Pageable):没有条件的分页
  8. * 返回:Page(springDataJpa为我们封装好的pageBean对象,数据列表,共条数)
  9. */
  10. @Test
  11. public void testSpec4() {
  12.  
  13. Specification spec = null;
  14. //PageRequest对象是Pageable接口的实现类
  15. /**
  16. * 创建PageRequest的过程中,需要调用他的构造方法传入两个参数
  17. * 第一个参数:当前查询的页数(从0开始)
  18. * 第二个参数:每页查询的数量
  19. */
  20. Pageable pageable = new PageRequest(0,2);
  21. //分页查询
  22. Page<Customer> page = customerSpecDao.findAll(null, pageable);
  23. System.out.println(page.getContent()); //得到当前页数据集合
  24. System.out.println(page.getTotalElements());//得到总条数
  25. System.out.println(page.getTotalPages());//得到总页数
  26. }

SpringData_03_Specifications动态查询的更多相关文章

  1. Thinkphp查询 1.查询方式 2.表达式查询 3.快捷查询 4.区间查询 5.组合查询 6.统计查询 7.动态查询 8.SQL 查询

    1.使用字符串作为条件查询 $user = M('User'); var_dump($user->where('id=1 AND user="蜡笔小新"')->sele ...

  2. Linq 动态查询排序

    Linq的排序一般是这样写的: query.OrderBy(x => x.Tel).Skip().Take(); 实际使用中排序字段可能是通过字符类型的参数来设置的,于是想这样实现: query ...

  3. ibatis动态查询条件

    ibatis的调试相对困难,出错的时候主要依据是log4生成的log文件和出错提示,这方面要能比较熟练的看懂. 下面这个配置基本上包含了最复杂的功能:分页\搜索\排序\缓存\传值Hash表\返回has ...

  4. 自己写的一个关于Linq to Entity 动态查询的例子

    这两天一直想写一个动态查询的方式,先是晚上查询了一下,发现大家写的差不多都是一样的[如:http://www.cnblogs.com/ASPNET2008/archive/2012/10/28/274 ...

  5. Linq动态查询简易解决之道(原创)

    因为项目需要使用Linq来查询数据,但是在多条件查询时,需要使用一大堆if(...!=string.empty)等判断条件感觉不是很优雅.网上搜索以下,大概找到了两种办法,一种是老外写的一个类,感觉用 ...

  6. SSH动态查询封装接口介绍

    SSH动态查询封装接口介绍 1.查询记录总条数 public int count(Class c,Object[][] eq,Object[][] like,String[] group,String ...

  7. Linq to sql 实现多条件的动态查询(方法一)

    /// <summary> /// Linq to sql 多字段动态查询 /// </summary> /// <returns></returns> ...

  8. Linq to Sql : 动态构造Expression进行动态查询

    原文:Linq to Sql : 动态构造Expression进行动态查询 前一篇在介绍动态查询时,提到一个问题:如何根据用户的输入条件,动态构造这个过滤条件表达式呢?Expression<Fu ...

  9. Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询

    原文:Linq to Sql:N层应用中的查询(下) : 根据条件进行动态查询 如果允许在UI层直接访问Linq to Sql的DataContext,可以省去很多问题,譬如在处理多表join的时候, ...

随机推荐

  1. 新建的maven项目里没有src

    百度上搜到一个网友的一句话:没筷子你就不吃饭了是吧 若有所思 自己新建一个src文件 然后, 由于已经转换,因此上图没有sources选项 然后就可以在文件中随意编写文件 如果想添加package,直 ...

  2. ICPC 2018 焦作区域赛

    // 2019.10.7 练习赛 // 赛题来源:2018 ICPC 焦作区域赛 // CF链接:http://codeforces.com/gym/102028 A Xu Xiake in Hena ...

  3. unittest(2)

    测试用例执行顺序 1.setUp和tearDown相关 setUp:表示前置条件,它在每一个用例执行之前必须会执行一次        setUp可以理解为我们需要自动化测试时,需要打开网页窗口,输入对 ...

  4. xargs - 从标准输入重建并执行命令行

    总览 (SYNOPSIS) xargs [-0prtx] [-e[eof-str]] [-i[replace-str]] [-l[max-lines]] [-n max-args] [-s max-c ...

  5. html编写的日历

    1.html (1) <html> <head> <meta http-equiv="Content-Type" content="text ...

  6. vue-router如何参数传递

    1.我们用<router-link>标签中的to属性进行传参,需要您注意的是这里的to要进行一个绑定,写成:to 先来看一下这种传参方法的基本语法: <router-link :to ...

  7. es5 JSON对象

    1. JSON.stringify(obj/arr) js对象(数组)转换为json对象(数组) 2. JSON.parse(json) json对象(数组)转换为js对象(数组) <!DOCT ...

  8. Java 多线程 - 锁的类型

    https://zhuanlan.zhihu.com/p/37287566 https://www.cnblogs.com/qifengshi/p/6831055.html

  9. flask中abort()函数的使用

    一.介绍 #从flask中导入abort from flask import abort abort()函数的作用 可以让开发者在检测到web访问错误时,立即将错误信息返回回去,返回的错误码必须是已知 ...

  10. vs数据库连接问题

    在swagger上测试时报错:数据库连接不上 原因:在项目中修改过connectionstring,但是每次编译时本地文件中并没有更新 修改: 修改配置文件属性:不复制 —> 始终复制