JPA--SpringDataJpa之Specifications动态查询

左手的ㄟ右手 2021-08-13 20:27 1063阅读 0赞

Specifications动态查询

JpaSpecificationExecutor 方法列表

  • T findOne(Specification spec):查询单个对象
  • List findAll(Specification spec):查询列表
  • Page findAll(Specification spec, Pageable pageable):分页查询

    • pageable:分页参数
    • 返回值:分页pageBean(page:是springdatajpa提供的)
  • List findAll(Specification spec, Sort sort):查询列表

    • Sort:排序参数
  • long count(Specification spec):统计查询

Specification :
Specification是查询条件,由我们自己实现。
需要实现Predicate toPredicate(Root root, CriteriaQuery<?> query, CriteriaBuilder cb)方法

  • root:查询的根对象(查询的任何属性都可以从根对象中获取)
  • CriteriaQuery:顶层查询对象,自定义查询方式(了解:一般不用)
  • CriteriaBuilder:查询的构造器,封装了很多的查询条件

示例

实体类

  1. package pers.zhang.entity;
  2. /** * @author zhang * @date 2019/12/15 - 22:10 */
  3. import javax.persistence.*;
  4. /** * 1.实体类和表的映射关系 * @Entity * @Table * 2.类中属性和表中字段的映射关系 * @Id * @GeneratedValue * @Colum */
  5. @Entity //声明实体类
  6. @Table(name="cst_customer") //建立实体类和表的映射关系
  7. public class Customer {
  8. @Id//声明当前私有属性为主键
  9. @GeneratedValue(strategy= GenerationType.IDENTITY) //配置主键的生成策略
  10. @Column(name="cust_id") //指定和表中cust_id字段的映射关系
  11. private Long custId;
  12. @Column(name="cust_name") //指定和表中cust_name字段的映射关系
  13. private String custName;
  14. @Column(name="cust_source")//指定和表中cust_source字段的映射关系
  15. private String custSource;
  16. @Column(name="cust_industry")//指定和表中cust_industry字段的映射关系
  17. private String custIndustry;
  18. @Column(name="cust_level")//指定和表中cust_level字段的映射关系
  19. private String custLevel;
  20. @Column(name="cust_address")//指定和表中cust_address字段的映射关系
  21. private String custAddress;
  22. @Column(name="cust_phone")//指定和表中cust_phone字段的映射关系
  23. private String custPhone;
  24. public Long getCustId() {
  25. return custId;
  26. }
  27. public void setCustId(Long custId) {
  28. this.custId = custId;
  29. }
  30. public String getCustName() {
  31. return custName;
  32. }
  33. public void setCustName(String custName) {
  34. this.custName = custName;
  35. }
  36. public String getCustSource() {
  37. return custSource;
  38. }
  39. public void setCustSource(String custSource) {
  40. this.custSource = custSource;
  41. }
  42. public String getCustIndustry() {
  43. return custIndustry;
  44. }
  45. public void setCustIndustry(String custIndustry) {
  46. this.custIndustry = custIndustry;
  47. }
  48. public String getCustLevel() {
  49. return custLevel;
  50. }
  51. public void setCustLevel(String custLevel) {
  52. this.custLevel = custLevel;
  53. }
  54. public String getCustAddress() {
  55. return custAddress;
  56. }
  57. public void setCustAddress(String custAddress) {
  58. this.custAddress = custAddress;
  59. }
  60. public String getCustPhone() {
  61. return custPhone;
  62. }
  63. public void setCustPhone(String custPhone) {
  64. this.custPhone = custPhone;
  65. }
  66. @Override
  67. public String toString() {
  68. return "Customer{" +
  69. "custId=" + custId +
  70. ", custName='" + custName + '\'' +
  71. ", custSource='" + custSource + '\'' +
  72. ", custIndustry='" + custIndustry + '\'' +
  73. ", custLevel='" + custLevel + '\'' +
  74. ", custAddress='" + custAddress + '\'' +
  75. ", custPhone='" + custPhone + '\'' +
  76. '}';
  77. }
  78. }

Dao接口

  1. public interface MyCustomerDao extends JpaRepository<Customer, Long>, JpaSpecificationExecutor<Customer> {
  2. }

测试类

  1. @RunWith(SpringJUnit4ClassRunner.class)
  2. @ContextConfiguration(locations = "classpath:applicationContext.xml")
  3. public class SpecTest {
  4. @Autowired
  5. private MyCustomerDao customerDao;
  6. }

根据条件查询单个对象










































方法名称 sql对应关系
equle filed = value
gt(greaterThan ) filed > value
lt(lessThan ) filed < value
ge(greaterThanOrEqualTo ) filed >= value
le( lessThanOrEqualTo) filed <= value
notEqule filed != value
like filed like value
notLike filed not like value
  1. @Test
  2. public void testSpec(){
  3. /* 自定义查询条件: 1.实现Specification接口(提供泛型:查询对象类型) 2.实现toPredicate方法(构造查询条件) 3.需要借助方法参数中的两个参数(root:获取需要查询的对象属性 CriteriaBuilder:构造查询条件的,内部封装了很多的查询条件(模糊匹配,精确匹配)) 示例:根据客户名称查询,查询客户名为网易的客户 查询条件: 1.查询方式 criteriaBuilder对象 2.比较的属性名称 root对象 */
  4. Specification<Customer> spec = new Specification<Customer>() {
  5. @Override
  6. public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
  7. //获取比较的属性
  8. Path<Object> custName = root.get("custName");
  9. //构造查询条件 select * from cst_customer where cust_name = '网易'
  10. //第一个参数:需要比较的属性
  11. //第二个参数:当前需要比较的取值
  12. Predicate predicate = criteriaBuilder.equal(custName, "网易");//精准匹配
  13. return predicate;
  14. }
  15. };
  16. Customer customer = customerDao.findOne(spec);
  17. System.out.println(customer);
  18. }

多条件查询单个值

  1. /* 多条件查询 示例:根据客户名(网页)和客户行业(游戏)查询客户 */
  2. @Test
  3. public void testSpec1(){
  4. /* root:获取属性(客户名,所属行业) criteriaBuilder: 1.构造客户名的精准匹配查询 2.构造所属行业的精准匹配查询 3.将以上两个查询联系起来 */
  5. Specification<Customer> spec = new Specification<Customer>() {
  6. @Override
  7. public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
  8. Path<Object> custName = root.get("custName");
  9. Path<Object> custIndustry = root.get("custIndustry");
  10. //构造查询参数
  11. //1.构造客户名的精准匹配
  12. Predicate p1 = criteriaBuilder.equal(custName, "网易");
  13. //2.构造所属行业的精准匹配
  14. Predicate p2 = criteriaBuilder.equal(custIndustry, "游戏");
  15. //3.将多个条件组合到一起,组合(满足条件一并且满足条件二:与关系 满足条件一或满足条件二即可:或关系)
  16. Predicate and = criteriaBuilder.and(p1, p2);//以与的形式拼接多个查询条件
  17. //criteriaBuilder.or() 以或的方式拼接条件
  18. return and;
  19. }
  20. };
  21. Customer customer = customerDao.findOne(spec);
  22. System.out.println(customer);
  23. }

查询列表

  1. /* 查询列表: 示例:根据客户名称模糊匹配,返回客户列表 criteriaBuilder的方法: equal:直接得到path对象(属性),然后进行比较 gt,lt,ge,le,like:得到path对象,根据句path指定比较的参数类型,再去进行比较 指定参数的类型:path.as(类型的字节码对象) */
  2. @Test
  3. public void testSpec3(){
  4. Specification<Customer> spec = new Specification<Customer>() {
  5. @Override
  6. public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
  7. Path<Object> custName = root.get("custName");
  8. Predicate predicate = criteriaBuilder.like(custName.as(String.class), "%腾%");
  9. return predicate;
  10. }
  11. };
  12. List<Customer> all = customerDao.findAll(spec);
  13. for(Customer c : all)
  14. System.out.println(c);
  15. }

排序查询

  1. /* 排序查询 示例:根据客户名称模糊匹配,逆序,返回客户列表 */
  2. @Test
  3. public void testSpec4(){
  4. Specification<Customer> spec = new Specification<Customer>() {
  5. @Override
  6. public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
  7. Path<Object> custName = root.get("custName");
  8. Predicate predicate = criteriaBuilder.like(custName.as(String.class), "%腾%");
  9. return predicate;
  10. }
  11. };
  12. /* 创建排序对象Sort 需要调用构造方法传递参数 1. 排序的顺序(asc | desc) 2. 排序的属性名 */
  13. Sort sort = new Sort(Sort.Direction.ASC, "custName");
  14. List<Customer> all = customerDao.findAll(spec);
  15. for(Customer c : all)
  16. System.out.println(c);
  17. }

分页查询
Page接口

  1. public interface Page<T> extends Iterable<T> {
  2. int getNumber(); //当前第几页 返回当前页的数目。总是非负的
  3. int getSize(); //返回当前页面的大小。
  4. int getTotalPages(); //返回分页总数。
  5. int getNumberOfElements(); //返回当前页上的元素数。
  6. long getTotalElements(); //返回元素总数。
  7. boolean hasPreviousPage(); //返回如果有上一页。
  8. boolean isFirstPage(); //返回当前页是否为第一页。
  9. boolean hasNextPage(); //返回如果有下一页。
  10. boolean isLastPage(); //返回当前页是否为最后一页。
  11. Iterator<T> iterator();
  12. List<T> getContent(); //将所有数据返回为List
  13. boolean hasContent(); //返回数据是否有内容。
  14. Sort getSort(); //返回页的排序参数。
  15. }

Pageable 接口:

  1. /** * 分页信息抽象接口 * * @author Oliver Gierke */
  2. public interface Pageable {
  3. /** * 返回要返回的页面. * * @return the page to be returned. */
  4. int getPageNumber();
  5. /** * 返回要返回的项目的数量。 * * @return the number of items of that page */
  6. int getPageSize();
  7. /** * 根据底层页面和页面大小返回偏移量。 * * @return the offset to be taken */
  8. int getOffset();
  9. /** * 返回排序参数。 * * @return */
  10. Sort getSort();
  11. }
  12. /* 分页查询: 1.findAll(Specification, Pageable):有条件的分页 2.findALL(Pageable):没有条件的分页 Specification:查询条件 Pageable:分页参数 返回:Page(springdataJpa为我们封装好的pageBean对象) */
  13. @Test
  14. public void testSpec5(){
  15. Specification spec = null;
  16. /* PageRequest是Pageable的实现类,在创建pageable的过程中,需要调用它的构造方法传入两个参数 1.当前查询的页数(从0开始) 2.每页查询的数量 */
  17. Pageable pageable = new PageRequest(0, 2);
  18. Page page = customerDao.findAll(spec, pageable);
  19. /* Page方法: getContent():获取查询的结果,返回List<?> getTotalElements():获取查询到的总条数,返回Long getTotalPages():获取查询到的总页数,返回int */
  20. System.out.println("数据:" + page.getContent());
  21. System.out.println("总条数:" + page.getTotalElements());
  22. System.out.println("总页数" + page.getTotalPages());
  23. }

发表评论

表情:
评论列表 (有 0 条评论,1063人围观)

还没有评论,来说两句吧...

相关阅读