惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - 时空穿越者

java并发:深入解析 ThreadPoolExecutor.addWorker() 流水线技术解析:处理器重排序的硬件基础 java并发:synchronized 揭秘 java并发:管道流(Piped Streams)的应用场景 java并发:再次认识一下Java中的锁 —— 类级别的锁是否存在? LangGraph:add_conditional_edges详解 Spring异步机制:@Async Spring BeanDefinition Spring Resource Spring之ApplicationContext Spring之BeanFactory:解析getBean()方法 Spring之IoC容器 Spring的整体架构 Spring Data JPA:解析CriteriaQuery Spring Data JPA:解析JpaSpecificationExecutor & Specification Spring Data JPA:解析SimpleJpaRepository java并发:线程池之Executors(ScheduledExecutorService篇) - 时空穿越者 java并发:线程池之饱和策略 java并发:线程池之ThreadPoolExecutor
Spring Data JPA:解析CriteriaBuilder
时空穿越者 · 2021-08-29 · via 博客园 - 时空穿越者

源码

在Spring Data JPA相关的文章[地址]中提到了有哪几种方式可以构建Specification的实例,该处需要借助CriteriaBuilder,回顾一下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);

解读:

CriteriaBuilder用于根据特定条件限制查询结果,请参见本文后面的示例。

CriteriaBuilder接口定义在包路径javax.persistence.criteria下,代码如下:

/**
 * Used to construct criteria queries, compound selections, 
 * expressions, predicates, orderings.
 *
 * <p> Note that <code>Predicate</code> is used instead of <code>Expression&#060;Boolean&#062;</code> 
 * in this API in order to work around the fact that Java 
 * generics are not compatible with varags.
 *
 * @since 2.0
 */
public interface CriteriaBuilder {

类图

方法定义

CriteriaBuilder中的一些方法如下图所示:

解读:

(1)CriteriaBuilder中的方法分为几个类别,譬如:ordering、aggregate functions、subqueries、equality、comparisons等等。

(2)CriteriaBuilder中的方法的返回值主要有CriteriaQuery、Expression、Predicate等几种类型。

示例

观察CriteriaBuilder中and方法与or方法的定义,如下:

    /**
     * Create a conjunction of the given boolean expressions.
     * @param x  boolean expression
     * @param y  boolean expression
     * @return and predicate
     */
    Predicate and(Expression<Boolean> x, Expression<Boolean> y);
    
    /**
     * Create a conjunction of the given restriction predicates.
     * A conjunction of zero predicates is true.
     * @param restrictions  zero or more restriction predicates
     * @return and predicate
     */
    Predicate and(Predicate... restrictions);

    /**
     * Create a disjunction of the given boolean expressions.
     * @param x  boolean expression
     * @param y  boolean expression
     * @return or predicate
     */
    Predicate or(Expression<Boolean> x, Expression<Boolean> y);

    /**
     * Create a disjunction of the given restriction predicates.
     * A disjunction of zero predicates is false.
     * @param restrictions  zero or more restriction predicates
     * @return or predicate
     */
    Predicate or(Predicate... restrictions);

解读:

上述and方法与or方法用于组合多个查询条件。

其中Predicate and(Predicate... restrictions);方法接受不定数参数Predicate... restrictions,故可以传入多个Predicate参数,最佳实践是传入一个数组;其意义是用and连接词将多个条件连接起来。

具体案例——添加多个查询条件

  private Specification createSpecification(Integer specialId, String specialEmail) {
    Specification<User> specification = new Specification<>() {
      @Override
      public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        Path id = root.get("id");
        Predicate predicateId = cb.gt(id, specialId);

        Path email = root.get("email");
        Predicate predicateEmail = cb.equal(email, specialEmail);
        
        return cb.and(predicateId, predicateEmail);
      }
    };

    return specification;
  }

解读:

上述着色处代码以and方法将两个条件组合在一起

扩展阅读

JPA Criteria Queries[地址]

Predicate与Expression

从前面的分析可知,CriteriaBuilder中的很多方法接受Expression或者Predicate类型的参数,并返回Expression或者Predicate类型的结果,譬如上面提到的and方法,所以本小节来探寻一下Expression与Predicate之间的关系。

Expression与Predicate之间的关系如下图所示:

解读:

Predicate接口继承了Expression接口,所以CriteriaBuilder中接受Expression类型参数的方法(譬如:and方法等)可以接受Predicate类型的参数,正如前面示例所展示的那样。

Note:

Path接口也继承了Expression接口,所以CriteriaBuilder中接受Expression类型参数的方法(譬如:lt方法)可以接受Path类型实例:

    Specification<User> specification = new Specification<>() {
      @Override
      public Predicate toPredicate(Root<User> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
        Path<Integer> path = root.get("id");
        return cb.lt(path, id);
      }
    };

解读:

上述示例在构造了Path类型的变量后调用了lt方法,该方法的定义如下:

    /**
     * Create a predicate for testing whether the first argument is 
     * less than the second.
     * @param x  expression
     * @param y  value
     * @return less-than predicate
     */
    Predicate lt(Expression<? extends Number> x, Number y);