JpaSpecificationExecutor接口

概述

封装 JPA Criteria 查询条件。通常使用匿名内部类的方式来创建该接口的对象

接口使用方式——Repository

public interface TaskPlanRepository extends JpaRepository<TaskPlan, String>, JpaSpecificationExecutor<TaskPlan> {

}

官方接口API:https://docs.spring.io/spring-data/jpa/docs/current/api/org/springframework/data/jpa/repository/JpaSpecificationExecutor.html

简单查询场景

public interface SpecificationExecutorRepository extends CrudRepository<User, Integer>,
        JpaSpecificationExecutor<User> {

}
@Service
public class SpecificationExecutorRepositoryManager {
    @Autowired
    private SpecificationExecutorRepository dao;
    /**
     * 描述:根据name来查询用户
     */
    public User findUserByName(final String name){
        return dao.findOne(new Specification<User>() {

            @Override
            public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query,
                    CriteriaBuilder cb) {
                Predicate predicate = cb.equal(root.get("name"), name);
                return predicate;
            }
        });
    }

    /**
     * 描述:根据name和email来查询用户
     */
    public User findUserByNameAndEmail(final String name, final String email){
        return dao.findOne(new Specification<User>() {

            @Override
            public Predicate toPredicate(Root<User> root,
                    CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> list = new ArrayList<Predicate>();
                Predicate predicate1 = cb.equal(root.get("name"), name);
                Predicate predicate2 = cb.equal(root.get("email"), email);
                list.add(predicate1);
                list.add(predicate2);
                // 注意此处的处理
                Predicate[] p = new Predicate[list.size()];
                return cb.and(list.toArray(p));
            }
        });
    }

    /**
     * 描述:组合查询
     */
    public User findUserByUser(final User userVo){
        return dao.findOne(new Specification<User>() {

            @Override
            public Predicate toPredicate(Root<User> root,
                    CriteriaQuery<?> query, CriteriaBuilder cb) {
                Predicate predicate = cb.equal(root.get("name"), userVo.getName());
                cb.and(predicate, cb.equal(root.get("email"), userVo.getEmail()));
                cb.and(predicate, cb.equal(root.get("password"), userVo.getPassword()));
                return predicate;
            }
        });
    }

    /**
     * 描述:范围查询in方法,例如查询用户id在[2,10]中的用户
     */
    public List<User> findUserByIds(final List<Integer> ids){
        return dao.findAll(new Specification<User>() {

            @Override
            public Predicate toPredicate(Root<User> root,
                    CriteriaQuery<?> query, CriteriaBuilder cb) {
                return root.in(ids);
            }
        });
    }

    /**
     * 描述:范围查询gt方法,例如查询用户id大于9的所有用户
     */
    public List<User> findUserByGtId(final int id){
        return dao.findAll(new Specification<User>() {

            @Override
            public Predicate toPredicate(Root<User> root,
                    CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.gt(root.get("id").as(Integer.class), id);
            }
        });
    }

    /**
     * 描述:范围查询lt方法,例如查询用户id小于10的用户
     */
    public List<User> findUserByLtId(final int id){
        return dao.findAll(new Specification<User>() {

            @Override
            public Predicate toPredicate(Root<User> root,
                    CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.lt(root.get("id").as(Integer.class), id);
            }
        });
    }

    /**
     * 描述:范围查询between方法,例如查询id在3和10之间的用户
     */
    public List<User> findUserBetweenId(final int start, final int end){
        return dao.findAll(new Specification<User>() {

            @Override
            public Predicate toPredicate(Root<User> root,
                    CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.between(root.get("id").as(Integer.class), start, end);
            }
        });
    }

    /**
     * 描述:排序和分页操作
     */
    public Page<User> findUserAndOrder(final int id){
        Sort sort = new Sort(Direction.DESC, "id");
        return dao.findAll(new Specification<User>() {

            @Override
            public Predicate toPredicate(Root<User> root,
                    CriteriaQuery<?> query, CriteriaBuilder cb) {
                return cb.gt(root.get("id").as(Integer.class), id);
            }
        }, new PageRequest(0, 5, sort));
    }

    /**
     * 描述:只有排序操作
     */
    public List<User> findUserAndOrderSecondMethod(final int id){
        return dao.findAll(new Specification<User>() {

            @Override
            public Predicate toPredicate(Root<User> root,
                    CriteriaQuery<?> query, CriteriaBuilder cb) {
                cb.gt(root.get("id").as(Integer.class), id);
                query.orderBy(cb.desc(root.get("id").as(Integer.class)));
                return query.getRestriction();
            }
        });
    }
}

复杂查询场景

  • 分页查询

  • 实现sql条件">=" 和 "<="的用法

greaterThanOrEqualTo代表 >= 当前条件时间, lessThanOrEqualTo代表<=当前条件时间,具体代码实现,参考上面的项目分页代码

  • 实现sql条件“=”的用法

equal的用法,详细参考上面的项目分页代码

同样的不要忘记notEqual方法

  • 实现sql条件“in”的用法

也是一整块分页代码,其中,in的使用方式,是我们关注的要点如下:

通过循环获取值,放到in的属性值里,在最后通过cb.or(in) 连接使用,打印的部分SQL如下:

  • 关联查询的用法

root.join("workManage2") 连接的是当前对象的关联属性对象,创建一个Join对象,就可以通过该join对象,通过查询条件,关联查询数据,具体使用,参考上面的作品分页查询代码

  • 关联实体类查询,就是关联Id查询

  • 实现sql条件“or”的用法、"like"的用法

根据上面的招标分页查询,or、like的用法如下:

具体实现参考招标分页查询实现

  • 排序用法

上面的是通过CriteriaBuilder实现排序,也可以通过Pageable的方式实现

具体实现参考招标分页查询实现、项目分页查询实现

Last updated

Was this helpful?