SpringDataJPA使用JpaSpecificationExecutor接口实现动态查询,排序,分页

SpringDataJPA中的dao层接口继承了JpaRepository接口和JpaSpecificationExecutor接口。

JpaSpecificationExecutor接口主要的方法有:

  • findOne(根据动态条件查询一条数据)
  • findAll(根据动态条件查询多条数据、可排序、可分页)
  • count(根据动态条件查询数据量)

直接贴测试代码吧,具体备注在代码中有注明

package cn.gpxxg.test;

import cn.gpxxg.dao.ICustomerDao;
import cn.gpxxg.domain.Customer;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import javax.persistence.criteria.*;
import java.util.List;

@RunWith(SpringJUnit4ClassRunner.class) // 表明使用spring的测试类
@ContextConfiguration(locations = "classpath:applicationContext.xml") // 读取spring的配置文件
public class JpaSpecificationTest {

    @Autowired
    private ICustomerDao dao;

    /**
     * 使用JpaSpecificationExecutor的findOne,查询一条数据
     * 案例:查询id为1的数据
     */
    @Test
    public void findOneTest()
    {
        /**
         * 匿名内部类
         * 自定义查询条件
         *      1、实现Specification接口(提供泛型,查询的对象实体类)
         *      2、实现toPredicate方法(该方法用于构造查询条件)
         *      3、需要借助方法中的两个参数
         *          Root<T> root:获取需要查询的对象属性
         *          CriteriaQuery<T> query:顶层查询对象(了解,一般不用)
         *          CriteriaBuilder cb:构造查询条件,内容封装了很多查询方式(模糊匹配、精准匹配...)
         *
         */
        Specification<Customer> spe = new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                Path<Object> id = root.get("id");
                Predicate predicate = cb.equal(id, 1);
                return predicate;
            }
        };
        Customer one = dao.findOne(spe);
        System.out.println(one);
    }


    /**
     * 使用JpaSpecificationExecutor的findAll,根据客户名模糊查询
     */
    @Test
    public void findAllTest1()
    {
        /**
         * 匿名内部类
         * 自定义查询条件
         *      1、实现Specification接口(提供泛型,查询的对象实体类)
         *      2、实现toPredicate方法(该方法用于构造查询条件)
         *      3、需要借助方法中的两个参数
         *          Root<T> root:获取需要查询的对象属性
         *          CriteriaQuery<T> query:顶层查询对象(了解,一般不用)
         *          CriteriaBuilder cb:构造查询条件,内容封装了很多查询方式(模糊匹配、精准匹配...)
         *
         */
        Specification<Customer> spe = new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                // 1、获取比较对象的属性
                Path<Object> custName = root.get("custName");

                // 2、定义查询方式:select * from customer where cust_name = '马德华'
                Predicate predicate = cb.equal(custName, "马德华");
                return predicate;
            }
        };

        // 传入条件,获取数据列表
        List<Customer> list = dao.findAll(spe);
        for (Customer customer : list) {
            System.out.println(customer);
        }
    }


    /**
     * 使用JpaSpecificationExecutor的findAll多条件查询,根据客户名模糊查询、客户地址精准查询
     * 注意:使用模糊查询时,需要告知参数的数据类型(String、Integer)
     */
    @Test
    public void findAllTest2()
    {
        Specification spe = new Specification() {
            public Predicate toPredicate(Root root, CriteriaQuery cq, CriteriaBuilder cb) {
                // 1、获取比较对象的属性
                Path custName = root.get("custName");
                Path custAddress = root.get("custAddress");

                // 2、定义查询方式:select * from customer where cust_name like '%马德华%' and cust_address = '西游记'
                Predicate p1 = cb.like(custName.as(String.class), "%马德华%");
                Predicate p2 = cb.equal(custAddress, "西游记");

                // 3、连接多个查询,返回Predicate
                Predicate predicate = cb.and(p1, p2);
                return predicate;
            }
        };

        List<Customer> list = dao.findAll(spe);
        for (Customer customer : list) {
            System.out.println(customer);
        }
    }


    /**
     * 使用JpaSpecificationExecutor的findAll,查询所有并根据id降序、cust_name升序
     * 使用Sort对象的构造方法传入排序类型和属性名称
     * 多个排序使用Sort对象的and方法连接
     */
    @Test
    public void findAllTest3()
    {
        // select * from sustomer order by id desc, cust_name asc
        Sort sort1 = new Sort(Sort.Direction.DESC, "id");
        Sort sort2 = new Sort(Sort.Direction.ASC, "custName");
        Sort and = sort1.and(sort2);
        List<Customer> list = dao.findAll(and);
        for (Customer customer : list) {
            System.out.println(customer);
        }
    }


    /**
     * 使用JpaSpecificationExecutor的findAll,查询所有custAddress等于"西游记"的客户,并分页
     */
    @Test
    public void findAllTest4()
    {
        Specification<Customer> spe = new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                Path<Object> custAddress = root.get("custAddress");
                Predicate predicate = cb.equal(custAddress, "西游记");
                return predicate;
            }
        };

        Pageable pageable = new PageRequest(0, 2);
        Page<Customer> page = dao.findAll(spe, pageable);
        // 获取查询出来的数据主体
        List<Customer> content = page.getContent();
        for (Customer customer : content) {
            System.out.println(customer);
        }

        // 获取符合条件的总条数
        long totalCount = page.getTotalElements();
        System.out.println("符合条件的总条数" + totalCount);

        // 获取符合条件的总页数
        int totalPages = page.getTotalPages();
        System.out.println("符合条件的总页数" + totalPages);
    }

    /**
     * 查询custAddress等于"西游记"的客户数量
     */
    @Test
    public void countTest()
    {
        Specification<Customer> spe = new Specification<Customer>() {
            public Predicate toPredicate(Root<Customer> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder cb) {
                Path<Object> custAddress = root.get("custAddress");
                Predicate predicate = cb.equal(custAddress, "西游记");
                return predicate;
            }
        };

        // 传入条件,获取结果
        long count = dao.count(spe);
        System.out.println(count);
    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值