• JPA Criteria 条件查询


    1. 概述

    在本教程中,我们将讨论一个非常有用的 JPA 功能 — 条件查询。

    它使我们能够在不执行原始SQL的情况下编写查询,并为我们提供了一些面向对象的查询控制,这是Hibernate的主要功能之一。标准 API 允许我们以编程方式构建标准查询对象,我们可以在其中应用不同类型的过滤规则和逻辑条件。

    从Hibernate5.2开始,Hibernate标准API被弃用,新的开发集中在JPA标准API上。我们将探讨如何使用Hibernate和JPA来构建条件查询。

    2. Maven 依赖项

    为了说明 API,我们将使用参考 JPA 实现 Hibernate。

    要使用 Hibernate,我们将确保将其最新版本添加到我们的pom.xml文件中:

    1. <dependency>
    2. <groupId>org.hibernate</groupId>
    3. <artifactId>hibernate-core</artifactId>
    4. <version>5.3.2.Final</version>
    5. </dependency>
    Copy

    我们可以在这里找到最新版本的Hibernate

    3. 使用标准的简单示例

    让我们首先看看如何使用条件查询检索数据。我们将了解如何从数据库中获取特定类的所有实例。

    我们有一个Item类,它表示元组“ITEM”在数据库中:

    1. public class Item implements Serializable {
    2. private Integer itemId;
    3. private String itemName;
    4. private String itemDescription;
    5. private Integer itemPrice;
    6. // standard setters and getters
    7. }
    Copy

    让我们看一个简单的条件查询,它将从数据库中检索“ITEM”的所有行:

    1. Session session = HibernateUtil.getHibernateSession();
    2. CriteriaBuilder cb = session.getCriteriaBuilder();
    3. CriteriaQuery<Item> cr = cb.createQuery(Item.class);
    4. Root<Item> root = cr.from(Item.class);
    5. cr.select(root);
    6. Query<Item> query = session.createQuery(cr);
    7. List<Item> results = query.getResultList();
    Copy

    上面的查询是如何获取所有项目的简单演示。让我们一步一步地看:

    1. 从会话工厂对象创建会话的实例
    2. 通过调用getCriteriaBuilder()方法创建 CriteriaBuilder的实例
    3. 通过调用CriteriaBuildercreateQuery()方法创建CriteriaQuery的实例
    4. 通过调用SessioncreateQuery() 方法创建查询实例
    5. 调用查询对象的getResultList() 方法,它给了我们结果

    现在我们已经介绍了基础知识,让我们继续讨论条件查询的一些功能。

    3.1. 使用表达式

    CriteriaBuilder 可用于根据特定条件限制查询结果,方法是使用CriteriaQuery where() 方法并提供由 CriteriaBuilder 创建的表达式。

    让我们看一些常用表达式的示例。

    为了获得价格超过1000的商品:

    cr.select(root).where(cb.gt(root.get("itemPrice"), 1000));Copy

    接下来,获取项目价格低于 1000 的项目:

    cr.select(root).where(cb.lt(root.get("itemPrice"), 1000));Copy

    具有项目名称的项目包含主席

    cr.select(root).where(cb.like(root.get("itemName"), "%chair%"));Copy

    itemPrice介于 100 和 200 之间的记录:

    cr.select(root).where(cb.between(root.get("itemPrice"), 100, 200));Copy

    在滑板油漆胶水中具有项目名称的项目:

    cr.select(root).where(root.get("itemName").in("Skate Board", "Paint", "Glue"));Copy

    要检查给定属性是否为空,请执行以下操作:

    cr.select(root).where(cb.isNull(root.get("itemDescription")));Copy

    要检查给定的属性是否不为空,请执行以下操作:

    cr.select(root).where(cb.isNotNull(root.get("itemDescription")));Copy

    我们还可以使用 isEmpty() 和isNotEmpty() 方法来测试类中的List是否为空。

    此外,我们可以结合上述两个或多个比较。标准 API 允许我们轻松地链接表达式

    1. Predicate[] predicates = new Predicate[2];
    2. predicates[0] = cb.isNull(root.get("itemDescription"));
    3. predicates[1] = cb.like(root.get("itemName"), "chair%");
    4. cr.select(root).where(predicates);
    Copy

    添加两个具有逻辑运算的表达式:

    1. Predicate greaterThanPrice = cb.gt(root.get("itemPrice"), 1000);
    2. Predicate chairItems = cb.like(root.get("itemName"), "Chair%");
    Copy

    具有上述定义条件的项目与逻辑 OR 连接:

    cr.select(root).where(cb.or(greaterThanPrice, chairItems));Copy

    要获取与上述定义条件匹配的项,请使用逻辑 AND 联接:

    cr.select(root).where(cb.and(greaterThanPrice, chairItems));Copy

    3.2. 排序

    现在我们知道了标准的基本用法,让我们看一下标准的排序功能。

    在下面的示例中,我们按名称的升序排列列表,然后按价格降序对列表进行排序:

    1. cr.orderBy(
    2. cb.asc(root.get("itemName")),
    3. cb.desc(root.get("itemPrice")));
    Copy

    在下一节中,我们将了解如何执行聚合函数。

    3.3. 投影、聚合和分组函数

    现在让我们看看不同的聚合函数。

    获取行计数:

    1. CriteriaQuery<Long> cr = cb.createQuery(Long.class);
    2. Root<Item> root = cr.from(Item.class);
    3. cr.select(cb.count(root));
    4. Query<Long> query = session.createQuery(cr);
    5. List<Long> itemProjected = query.getResultList();
    Copy

    以下是聚合函数的示例 -平均值聚合函数:

    1. CriteriaQuery<Double> cr = cb.createQuery(Double.class);
    2. Root<Item> root = cr.from(Item.class);
    3. cr.select(cb.avg(root.get("itemPrice")));
    4. Query<Double> query = session.createQuery(cr);
    5. List avgItemPriceList = query.getResultList();
    Copy

    其他有用的聚合方法有sum(),max(),min(),count()等。

    3.4.标准更新

    从 JPA 2.1 开始,支持使用条件API 执行数据库更新。

    CriteriaUpdate有一个set() 方法,可用于为数据库记录提供新值:

    1. CriteriaUpdate<Item> criteriaUpdate = cb.createCriteriaUpdate(Item.class);
    2. Root<Item> root = criteriaUpdate.from(Item.class);
    3. criteriaUpdate.set("itemPrice", newPrice);
    4. criteriaUpdate.where(cb.equal(root.get("itemPrice"), oldPrice));
    5. Transaction transaction = session.beginTransaction();
    6. session.createQuery(criteriaUpdate).executeUpdate();
    7. transaction.commit();
    Copy

    在上面的代码片段中,我们从CriteriaBuilder创建一个CriteriaUpdate 的实例,并使用其set() 方法为itemPrice 提供新值。为了更新多个属性,我们只需要多次调用set() 方法。

    3.5.条件删除

    条件删除启用使用条件API 的删除操作。

    我们只需要创建一个CriteriaDelete的实例并使用where() 方法来应用限制:

    1. CriteriaDelete<Item> criteriaDelete = cb.createCriteriaDelete(Item.class);
    2. Root<Item> root = criteriaDelete.from(Item.class);
    3. criteriaDelete.where(cb.greaterThan(root.get("itemPrice"), targetPrice));
    4. Transaction transaction = session.beginTransaction();
    5. session.createQuery(criteriaDelete).executeUpdate();
    6. transaction.commit();
    Copy

    4. 优于 HQL 的优势

    在前面的部分中,我们介绍了如何使用条件查询。

    显然,与 HQL 相比,标准查询的主要和最强大的优势是漂亮、干净、面向对象的 API。

    与普通 HQL 相比,我们可以简单地编写更灵活、更动态的查询。该逻辑可以使用 IDE 进行重构,并具有 Java 语言本身的所有类型安全优势。

    当然,也有一些缺点,尤其是在更复杂的连接周围。

    因此,我们通常必须使用最适合工作的工具——在大多数情况下,这可能是标准 API,但肯定在某些情况下,我们将不得不降低级别。

    5. 结论

    在本文中,我们重点介绍了 Hibernate 和 JPA 中标准查询的基础知识以及 API 的一些高级功能。

    此处讨论的代码在GitHub 存储库中可用。

  • 相关阅读:
    神经网络参数优化算法,神经网络参数优化方案
    使用Mac的Applescript定制sublime执行C/C++程序弹出终端
    windows系统cmake生成动态库无lib文件解决方法
    Bootstrap Blazor 使用模板创建项目
    SpringBoot集成支付宝 - 少走弯路就看这篇
    XLua热更新框架原理和代码实战
    [JavaScript]_[初级]_[关于forof或者for...of循环语句的用法]
    DASCTF X GFCTF 2022十月挑战赛web
    linux安装&git安装
    git忽略提交文件
  • 原文地址:https://blog.csdn.net/allway2/article/details/128117661