zoukankan      html  css  js  c++  java
  • Spring Data JPA:解析CriteriaQuery

    CriteriaQuery 

    源码定义

    CriteriaQuery定义在包路径javax.persistence.criteria下,其定义如下:

    /**
     * The <code>CriteriaQuery</code> interface defines functionality that is specific 
     * to top-level queries.
     *
     * @param <T>  the type of the defined result
     *
     * @since 2.0
     */
    public interface CriteriaQuery<T> extends AbstractQuery<T> {

    类图

    CriteriaQuery对应的类图如下:

      

    方法定义

    此处聚焦CriteriaQuery继承体系中定义了哪些方法,请参见下图:

    解读:

    根据上述方法的返回值可知,AbstractQuery、CriteriaQuery接口中的方法大部分是返回其本身类型变量,可以理解为流式API的写法。

    实际应用

    回顾一下Specification中toPredicate方法的定义,代码如下:

        /**
         * Creates a WHERE clause for a query of the referenced entity in form of a {@link Predicate} for the given
         * {@link Root} and {@link CriteriaQuery}.
         *
         * @param root must not be {@literal null}.
         * @param query must not be {@literal null}.
         * @param criteriaBuilder must not be {@literal null}.
         * @return a {@link Predicate}, may be {@literal null}.
         */
        @Nullable
        Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder criteriaBuilder);

    解读:

    上述方法的第二个参数为CriteriaQuery类型,所以在构建Specification的实例(实现其toPredicate方法)时可以借助CriteriaQuery的能力,案例如下:

      public Page<User> getUsers(Integer id, Integer pageNum, Integer pageSize) {
        Sort sort = Sort.by(Sort.Direction.DESC, "id");
        Pageable pageable = PageRequest.of(pageNum, pageSize, sort);
    
        Specification<User> specification = new Specification<>() {
          @Override
          public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
            Path<Integer> idPath = root.get("id");
    
            query.where(cb.lt(idPath, id));
            query.orderBy(cb.asc(idPath));
    
            return query.getRestriction();
          }
        };
        return userRepository.findAll(specification, pageable);
      }

    解读:

    上述案例调用了CriteriaQuery的where以及orderBy方法以指定具体查询条件,在return语句中调用了CriteriaQuery的getRestriction方法。

    Note:

    从前面类图可知,getRestriction方法实际上是定义在CommonAbstractCriteria接口中,代码如下:

    /**
     * The <code>CommonAbstractCriteria</code> interface defines functionality 
     * that is common to both top-level criteria queries and subqueries as 
     * well as to update and delete criteria operations.
     * It is not intended to be used directly in query construction.
     *
     * <p> Note that criteria queries and criteria update and delete operations
     * are typed differently.
     * Criteria queries are typed according to the query result type.
     * Update and delete operations are typed according to the target of the
     * update or delete.
     *
     * @since 2.1
     */
    public interface CommonAbstractCriteria {
    
        /**
         * Create a subquery of the query. 
         * @param type  the subquery result type
         * @return subquery 
         */
        <U> Subquery<U> subquery(Class<U> type);
    
        /**
         * Return the predicate that corresponds to the where clause
         * restriction(s), or null if no restrictions have been
         * specified.
         * @return where clause predicate
         */
        Predicate getRestriction();
     
    }

    CriteriaQuery与EntityManager

    EntityManager定义在包路径javax.persistence下,其中的一些方法如下图所示:

    解读:

    EntityManager提供了众多createQuery方法,其中一个createQuery方法可以接受CriteriaQuery类型的参数,该方法的定义如下:

        /**
         * Create an instance of <code>TypedQuery</code> for executing a
         * criteria query.
         * @param criteriaQuery  a criteria query object
         * @return the new query instance
         * @throws IllegalArgumentException if the criteria query is
         *         found to be invalid
         * @since 2.0
         */
        public <T> TypedQuery<T> createQuery(CriteriaQuery<T> criteriaQuery); 

    示例

      private void getUserList(String specialEmail) {
        CriteriaBuilder cb = entityManager.getCriteriaBuilder();
        CriteriaQuery<User> query = cb.createQuery(User.class);
    
        Root<User> root = query.from(User.class);
    
        Path<User> email = root.get("email");
        Predicate predicateEmail = cb.equal(email, specialEmail);
        query.where(predicateEmail);
    
        TypedQuery<User> q = entityManager.createQuery(query);
        List<User> result = q.getResultList();
        for (User user : result) {
          //打印查询结果
          System.out.println(user.toString());
        }
      }

    解读:

    上述代码通过EntityManager的getCriteriaBuilder方法获取了CriteriaBuilder类型的变量,进而构建了CriteriaQuery类型的变量,然后进一步利用CriteriaQuery中的from、where等方法指定查询条件。

    扩展阅读

    官方文档[地址]

    其它[地址]

  • 相关阅读:
    「BZOJ 1297」「SCOI 2009」迷路「矩阵乘法」
    「BZOJ 1831」「AHOI 2008」逆序对「贪心」
    「BZOJ 1791」「IOI 2008」Island「基环树」
    WC2019 冬眠记
    「ZOJ 1354」Extended Lights Out「高斯消元」
    「BZOJ 3270」博物馆「高斯消元」
    「学习笔记」泰勒级数
    获取iPhone的UDID
    面试题
    Java的post(HTTPS)请求-----接口测试
  • 原文地址:https://www.cnblogs.com/studyLog-share/p/15189946.html
Copyright © 2011-2022 走看看