7、Spring Data JPA 之 Specifications动态查询

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

抽象方法有JpaSpecificationExecutor提供

方法都需要传入一个Specification对象,该对象也是借口

里面只有一个方法,可以通过匿名内部类的实现方式实现


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:applicationContext.xml")//指定spring容器的配置信息
public class SpecTest {

    @Autowired
    private UsersDao usersDao;

    @Test
    public void testSpec(){
        /**
         * 匿名内部类
         *
         * 自定义查询条件
         *      1、实现Specification接口(提供返现,查询的对象类型)
         *      2、实现toPredicate方法(构造查询条件)
         *      3、需要借助方法参数中的两个参数
         *          root:获取需要查询的对象属性
         *          CriteriaBuilder: 构造查询条件的,内部封装了很多的查询条件(模糊匹配,精准匹配)
         *
         *  根据用户名查询
         */
        Specification<Users> spec = new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                //获取比较的属性
                Path<Object> userName = root.get("userName");
                //构造查询条件
                Predicate predicate = criteriaBuilder.equal(userName, "小黑 ");
                return predicate;
            }
        };
        Users users = usersDao.findOne(spec);
        System.out.println(users);
    }

    /**
     * 多条件查询
     *      案例:根据用户名和用户id进行查询
     */
    @Test
    public void testSpec1(){

        Specification<Users> spec = new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                Path<Object> userName = root.get("userName");
                Path<Object> userId = root.get("userId");

                Predicate p1 = criteriaBuilder.equal(userName, "小黑");
                Predicate p2 = criteriaBuilder.equal(userId, 1);

                Predicate result = criteriaBuilder.and(p1, p2);

                return result;
            }
        };
        Users user = usersDao.findOne(spec);
        System.out.println(user);
    }

    /**
     *  根据用户名称的模糊匹配,返回客户列表
     *      equal 方法直接得到path对象(属性),然后进行比较即可
     *      gt,lt,ge,le,like 方法得到Path独享,根据path指定比较的参数类型,再去进行比较
     *              指定参数类型,path.as(类型的字节码对象)
     */
    @Test
    public void testSpec3(){
        Specification<Users> spec = new Specification<Users>() {
            @Override
            public Predicate toPredicate(Root<Users> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {

                Path<Object> userName = root.get("userName");

                Predicate like = criteriaBuilder.like(userName.as(String.class), "%小%");

                return like;
            }
        };
//        List<Users> all = usersDao.findAll(spec);
//        for (Users user: all
//             ) {
//            System.out.println(user);
//        }
        /**添加排序
         * 创建排序对象
         *      第一个参数:排序的顺序
         *      第二个参数:排序的属性名称
         */
        Sort sort = new Sort(Sort.Direction.DESC, "userId");
        List<Users> all = usersDao.findAll(spec, sort);
        for (Users user: all
             ) {
            System.out.println(user);
        }
    }

    /**
     * 分页查询
     */
    @Test
    public void testSpec4(){
        Specification spec = null;
        /**
         * 创建PageRequest的工程中,需要调用他的构造方法传入两个参数
         *      第一个参数: 当前查询的页数(从0开始)
         *      第二个参数: 每页查询的数量
         */
        Pageable pageable = new PageRequest(0,2);
        //分页查询
        Page<Users> page = usersDao.findAll(null, pageable);
        //得到数据集合列表
        System.out.println(page.getContent());
        //得到总条数
        System.out.println(page.getTotalElements());
        //得到总页数
        System.out.println(page.getTotalPages());
    }
}
posted @ 2020-08-18 08:46  lawrence林  阅读(320)  评论(0编辑  收藏  举报