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

    1. Predicate toPredicate(Root<T> var1, CriteriaQuery<?> var2, CriteriaBuilder var3);
    2. //封装查询条件

    代码实例

    1. package com.cedric.test;
    2. import com.cedric.dao.CustomerDao;
    3. import com.cedric.domain.Customer;
    4. import org.junit.Test;
    5. import org.junit.runner.RunWith;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.data.domain.Page;
    8. import org.springframework.data.domain.PageRequest;
    9. import org.springframework.data.domain.Pageable;
    10. import org.springframework.data.domain.Sort;
    11. import org.springframework.data.jpa.domain.Specification;
    12. import org.springframework.test.context.ContextConfiguration;
    13. import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
    14. import javax.persistence.criteria.*;
    15. import java.util.List;
    16. @RunWith(SpringJUnit4ClassRunner.class)
    17. @ContextConfiguration(locations = "classpath:applicationContext.xml")
    18. public class SpecTest {
    19. @Autowired
    20. private CustomerDao customerDao;
    21. /**
    22. * 根据条件,查询单个对象
    23. */
    24. @Test
    25. public void testSpec(){
    26. /**
    27. * 自定义查询条件
    28. * 1.实现Specification接口(提供泛型,查询的对象类型)
    29. * 2.实现toPredicate方法(构造查询条件)
    30. * 3.需要借助方法参数中的两个参数(
    31. * root:获取需要查询的对象属性
    32. * CriteriaBuilder:构造查询条件的内部封装了很多查询条件(模糊匹配,精准匹配)
    33. * )
    34. *
    35. * 案例:根据客户名称查询,查询客户名为京东的客户
    36. * 查询条件
    37. * 1.查询方式
    38. * cb对象
    39. * 2.比较的属性名称
    40. * root对象
    41. */
    42. Specification<Customer> spec = new Specification<Customer>() {
    43. @Override
    44. public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
    45. // 1.获取比较的属性
    46. Path<Object> custName = root.get("custName");
    47. // 2.构造查询条件 : select * from cst_customer where cust_name = '京东'
    48. /**
    49. * 第一个参数:需要比较的属性(path对象)
    50. * 第二个参数:当前需要比较的取值
    51. */
    52. Predicate predicate = criteriaBuilder.equal(custName, "京东");//进行精准匹配(比较的属性,比较的属性取值)
    53. return predicate;
    54. }
    55. };
    56. Customer customer = customerDao.findOne(spec);
    57. System.out.println(customer);
    58. }
    59. /**
    60. * 多条件查询
    61. * 案例:根据客户名(腾讯)和客户所属行业查询(网游)
    62. */
    63. @Test
    64. public void testSpec1(){
    65. /**
    66. * root:获取属性
    67. * 客户名
    68. * 所属行业
    69. * criteriaBuilder:构造查询
    70. * 1.构造客户名的精准匹配查询
    71. * 2.构造所属行业的精准匹配查询
    72. * 3.将以上两个查询联系起来
    73. */
    74. Specification<Customer> spec = new Specification<Customer>() {
    75. @Override
    76. public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
    77. Path<Object> custName = root.get("custName");//客户名
    78. Path<Object> custIndustry = root.get("custIndustry");//所属行业
    79. //构造函数
    80. //1.构造客户名的精准匹配查询
    81. Predicate predicate = criteriaBuilder.equal(custName, "腾讯");// 第一个参数,path(属性),第二个参数,属性的取值
    82. //2.构造所属行业的精准匹配查询
    83. Predicate predicate1 = criteriaBuilder.equal(custIndustry, "网游");
    84. //3.将多个查询条件组合到一起:组合(满足条件一并且满足条件二:与关系,满足条件一或满足条件二即可:或关系)
    85. Predicate and = criteriaBuilder.and(predicate, predicate1);//以与的形式拼接多个查询条件
    86. //criteriaBuilder.or();//以或的形式拼接多个查询条件
    87. return and;
    88. }
    89. };
    90. Customer customer = customerDao.findOne(spec);
    91. System.out.println(customer);
    92. }
    93. /**
    94. * 案例:完美根据客户名称的模糊匹配,返回客户列表
    95. * 客户名称以‘阿里’开头
    96. * equal:直接得到path对象(属性),然后进行比较即可
    97. * gt,lt,ge,le,like:得到path对象,根据path指定比较的参数类型,再去进行比较
    98. * 指定参数类型:path.as(类型的字节码对象)
    99. */
    100. @Test
    101. public void testSpec3(){
    102. //构造查询条件
    103. Specification<Customer> spec = new Specification<Customer>() {
    104. @Override
    105. public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
    106. //查询属性:用户名
    107. Path<Object> custName = root.get("custName");
    108. //查询方式:模糊匹配
    109. Predicate like = criteriaBuilder.like(custName.as(String.class), "阿里%");
    110. return like;
    111. }
    112. };
    113. /* ListCustomer> all = customerDao.findAll(spec);
    114. for(Customer customer : all){
    115. System.out.println(customer);
    116. }*/
    117. //添加排序
    118. //创建排序对象,需要调用构造方法实例化sort对象
    119. //第一个参数:排序的顺序(倒序,正序)
    120. //Sort.Direction.DESC:倒序
    121. //Sort.Direction.ASC:升序
    122. //第二个参数:排序的属性名称
    123. Sort sort = new Sort(Sort.Direction.DESC,"custId");
    124. List<Customer> all = customerDao.findAll(spec, sort);
    125. for(Customer customer : all){
    126. System.out.println(customer);
    127. }
    128. }
    129. /**
    130. * 分页查询
    131. * Specification:查询条件
    132. * Pageable:分页参数
    133. * 分页参数:查询的页码,每页查询的条数
    134. * findAll(Specification,Pageable):带有条件的分页
    135. * findAll(Pageable):没有条件的分页
    136. * 返回:Page(SpringDataJpa为我们封装好的pageBean对象,数据列表,总条数)
    137. */
    138. @Test
    139. public void testSpec4(){
    140. Specification spec = null;
    141. //PageRequest对象是Pageable接口的实现类
    142. /**
    143. * 创建PageRequest的过程中,需要调用他的构造方法传入两个参数
    144. * 第一个参数:当前查询的页数(从0开始)
    145. * 第二个参数:每页查询的数量
    146. */
    147. Pageable pageable = new PageRequest(0,2);
    148. // 分页查询
    149. Page<Customer> page = customerDao.findAll(null, pageable);
    150. System.out.println(page.getContent());//得到数据集合列表
    151. System.out.println(page.getTotalElements());//得到总条数
    152. System.out.println(page.getTotalPages());//得到总页数
    153. }
    154. }