四、Spring Data JPA使用Specification动态查询

Dao接口

public interface CustomerDao extends JpaRepository<Customer,Long>,JpaSpecificationExecutor<Customer> {
}

测试方法:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")
public class SpecTest {
    @Autowired
    private CustomerDao customerDao;
    /**
     * 自定义查询条件
     *      1.实现Specification接口(提供泛型:查询的对象类型)
     *      2.实现toPredicate方法(构造查询条件)
     *      3.需要借助方法参数中的两个参数(
     *                     root:获取需要查询的对象属性
     *          CriteriaBuilder:构造查询条件的,内部封装了很多的查询条件(模糊匹配,精准匹配)
     *       )
     *       predicate: 谓语;述语  criteria(criterion) 标准;准则;规范;准据
     *  案例:根据客户名称查询,查询客户名为百度的客户
     *          查询条件
     *              1.查询方式:cb对象
     *              2.比较的属性名称:root对象
     */
    @Test
    public void testSpec() {
        Specification<Customer> spec = new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //1.获取比较的属性
                Path<Object> custName = root.get("custName");
                //2.构造查询条件:select * from cst_customer where cust_name = '百度'
                /**
                 * 第一个参数:需要比较的属性(path对象)
                 * 第二个参数:当前需要比较的取值
                 */
                Predicate predicate = cb.equal(custName, "百度");//进行精准的匹配(比较的属性,比较的属性的取值)
                return predicate;
            }
        };
        Customer customer = customerDao.findOne(spec);
        System.out.println(customer);
    }

    /**
     * 多条件查询
     *      案例:根据客户名(新东方)和客户所属行业查询(教育)
     *          root: 获取属性,客户名,所属行业
     *           cb:  构造查询
     *               1.构造客户名的精准匹配查询
     *               2.构造所属行业的精准匹配查询
     *               3.将以上两个查询联系起来
     */
    @Test
    public void testSpec1() {
        Specification<Customer> spec = new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                Path<Object> custName = root.get("custName");//客户名
                Path<Object> custIndustry = root.get("custIndustry");//所属行业
                //构造查询
                //1、构造客户名的精准匹配查询
                Predicate p1 = cb.equal(custName, "新东方");
                //2、构造所属行业的精准匹配查询
                Predicate p2 = cb.equal(custIndustry, "教育");
                //3、将多个查询条件组合到一起:组合(满足条件一并且满足条件二:与关系,满足条件一或满足条件二即可:或关系)
                Predicate predicate = cb.and(p1, p2);//以与的形式拼接多个查询条件
                // cb.or();//以或的形式拼接多个查询条件
                return predicate;
            }
        };
        Customer customer = customerDao.findOne(spec);
        System.out.println(customer);
    }
    /**
     * 完成根据客户名称的模糊查询,返回客户列表
     *
     * equal: 直接的到path对象(属性),然后进行比较即可
     * gt,lt,ge,le,like : 得到path对象,根据path指定比较的参数类型,再去进行比较
     *      指定参数类型:path.as(类型的字节码对象)
     *
     * 添加排序: 创建排序对象,需要调用带参数的构造方法实例化sort对象
     *              第一个参数:排序的顺序(倒序,正序)
     *                        Sort.Direction.DESC:倒序
     *                        Sort.Direction.ASC: 升序
     *              第二个参数:排序的属性名称
     */
    @Test
    public void testSpec3() {
        // 构造查询条件参数
        Specification<Customer> spec = new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                //查询属性:客户名
                Path<Object> custName = root.get("custName");
                //查询方式:模糊匹配
                Predicate predicate = cb.like(custName.as(String.class), "%美%");
                return predicate;
            }
        };
        // 排序参数
        Sort sort = new Sort(Sort.Direction.DESC,"custId");
        // 按照条件查询,并且添加排序参数
        List<Customer> list2 = customerDao.findAll(spec, sort);
        for (Customer customer : list2) {
            System.out.println(customer);
        }
    }

    /**
     * 分页查询:
     *      Specification: 查询条件
     *      Pageable:      分页参数
     *          分页参数:    查询的页码,每页查询的条数
     *          findAll(Specification,Pageable): 带有条件的分页
     *                        findAll(Pageable): 没有条件的分页
     *  返回:Page(springDataJpa为我们封装好的pageBean对象,数据列表,共条数)
     *  PageRequest对象是Pageable接口的实现类
     *  创建PageRequest的过程中,需要调用他的构造方法传入两个参数
     *      第一个参数:当前查询的页数(从0开始)
     *      第二个参数:每页查询的数量
     */
    @Test
    public void testSpec4() {
        // 分页查询参数
        Pageable pageable = new PageRequest(0,2);
        // 分页查询
        Page<Customer> page = customerDao.findAll(null, pageable);
        System.out.println(page.getContent()); //得到每页数据集合列表
        System.out.println(page.getTotalElements());//得到总条数
        System.out.println(page.getTotalPages());//得到总页数
    }
}
[Customer{custId=2, custAddress='null', custIndustry='互联网', custLevel='null', custName='百度', custPhone='null', custSource='null'}, 
Customer{custId=3, custAddress='null', custIndustry='互联网', custLevel='null', custName='阿里巴巴', custPhone='null', custSource='null'}]
12
6

你可能感兴趣的:(Spring,Data,JPA)