正确使用 JPA criteria API、Predicates 和 CriteriaQuery 的 where 方法

2023-11-24

我正在尝试测试 JPA 存储库。这是我的客户端/测试代码:

@Test
    public void testFindBoitesByMultiFieldWithIdentifiantSet() {
        BoiteDataOnDemand dod = new BoiteDataOnDemand();
        Boite boite = dod.getSpecificBoite(0);
        boite.setIdentifiant("theIdentifiant");
        boiteRepository.save(boite);
        assertEquals(10, Boite.countBoites());
        BoiteQueryInfo boiteQueryInfo = new BoiteQueryInfo();
        boiteQueryInfo.setIdentifiant("theIdentifiant");
        List<Boite> boites = boiteRepository.findBoitesByMultiField(boiteQueryInfo, 1, 5, "identifiant", "desc");
        assertEquals(1, boites.size());
    }

这是存储库方法:

@Override
    public List<Boite> findBoitesByMultiField(BoiteQueryInfo boiteQueryInfo, Integer firstResult_, Integer maxResults_, String sort_, String order_) {
        log.debug("findBoitesByMultiField");

        final String identifiant = boiteQueryInfo.getIdentifiant();
        final Date dateOuvertureFrom = boiteQueryInfo.getDateOuvertureFrom();

        CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
        CriteriaQuery<Boite> c = criteriaBuilder.createQuery(Boite.class);
        Root<Boite> boite = c.from(Boite.class);
        List<Predicate> criteria = new ArrayList<Predicate>();
            ...
        if (identifiant != null && !identifiant.trim().equals("")) {
            ParameterExpression<String> parameter = criteriaBuilder.parameter(String.class, "identifiant");
            Predicate condition = criteriaBuilder.like(boite.<String> get("identifiant"), parameter);
            criteria.add(condition);
        }

        if (dateOuvertureFrom != null && dateOuvertureTo != null) {
            ParameterExpression<Date> parameterDateOuvertureFrom = criteriaBuilder.parameter(Date.class, "dateOuvertureFrom");
            ParameterExpression<Date> parameterDateOuvertureTo = criteriaBuilder.parameter(Date.class, "dateOuvertureTo");
            Predicate condition = criteriaBuilder.between(boite.<Date> get("dateOuverture"), parameterDateOuvertureFrom, parameterDateOuvertureTo);
            criteria.add(condition);
        } else if (dateOuvertureFrom != null) {
            ParameterExpression<Date> parameter = criteriaBuilder.parameter(Date.class, "dateOuvertureFrom");
            Predicate condition = criteriaBuilder.greaterThanOrEqualTo(boite.<Date> get("dateOuverture"), parameter);
            criteria.add(condition);
        } else if (dateOuvertureTo != null) {
            ParameterExpression<Date> parameter = criteriaBuilder.parameter(Date.class, "dateOuvertureTo");
            Predicate condition = criteriaBuilder.lessThanOrEqualTo(boite.<Date> get("dateOuverture"), parameter);
            criteria.add(condition);
        }

            ...    
        if (order.equalsIgnoreCase("desc")) {
            c.orderBy(criteriaBuilder.desc(boite.get(sort)));
        } else {
            c.orderBy(criteriaBuilder.asc(boite.get(sort)));
        }

        for (Predicate predicate : criteria) {
            c.where(criteriaBuilder.and(predicate));
        }

        TypedQuery<Boite> q = em.createQuery(c);

        if (identifiant != null && !identifiant.trim().equals("")) {
            q.setParameter("identifiant", "%" + identifiant + "%");
        }

        if (dateOuvertureFrom != null && dateOuvertureTo != null) {
            q.setParameter("dateOuvertureFrom", dateOuvertureFrom);
            q.setParameter("dateOuvertureTo", dateOuvertureTo);
        } else if (dateOuvertureFrom != null) {
            q.setParameter("dateOuvertureFrom", dateOuvertureFrom);
        } else if (dateOuvertureTo != null) {
            q.setParameter("dateOuvertureTo", dateOuvertureTo);
        }

            ...    
        return q.setFirstResult(firstResult).setMaxResults(maxResults).getResultList();
    }

然而,测试总是失败assertEquals(1, boites.size());表示没有返回结果,即(java.lang.AssertionError: expected:<1> but was:<0>).

我强烈怀疑这里出了问题:

for (Predicate predicate : criteria) {
            c.where(criteriaBuilder.and(predicate));
        }

但我不确定如何“和”标准。

有人可以提供建议吗?

附:供参考,BoiteDataOnDemand随机插入 10 行到boite table.

编辑:代码被编辑以使其更短。


从您在帖子最后部分的提示开始,我同意您为where条款不正确。

我看到两种处理方式:

第一种方式

使用谓词数组

List<Predicate> predicates = new ArrayList<Predicate>();
for (Key key : keys) {
    predicates.add(criteriaBuilder.equal(root.get(key), value));
}
c.where(criteriaBuilder.and(predicates.toArray(new Predicate[] {})));

第二种方式

在循环中修改相同的谓词

Predicate predicate = criteriaBuilder.conjunction();
for (Key key : keys) {
    Predicate newPredicate = criteriaBuilder.equal(root.get(key), value);
    predicate = criteriaBuilder.and(predicate, newPredicate);
}
c.where(predicate);

EDITED

再次查看您的代码示例后,我发现您已经以正确的方式创建了一个列表PredicateS:你已经叫它了criteria。您只是以错误的方式使用它们。请参阅我的第一个示例的最后一行。


EDIT 2

为了查看问题是否是由使用产生的PredicateExpressionS,在您的情况下不是特别需要的,请尝试暂时删除它们。修改您的第一个标准

if (identifiant != null && !identifiant.trim().equals("")) {
    ParameterExpression<String> parameter = criteriaBuilder.parameter(String.class, "identifiant");
    Predicate condition = criteriaBuilder.like(boite.<String> get("identifiant"), parameter);
    criteria.add(condition);
}

to

if (identifiant != null && !identifiant.trim().equals("")) {
    Predicate condition = criteriaBuilder.like(boite.get("identifiant"), "%" + identifiant + "%");
    criteria.add(condition);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

正确使用 JPA criteria API、Predicates 和 CriteriaQuery 的 where 方法 的相关文章

随机推荐

  • 刷新页面时 Socket IO 建立多个连接 - Node JS

    我开发了一个抓取工具 可以从所有网站抓取作业并将其保存到数据库中 我已经制作了自己的默认日志 在其中获取消息 错误 信息 等 我正在使用 socket io 来实时更新我的 视图以及数据库 问题是当我启动应用程序时 它完美地建立了套接字和数
  • 理想的 terraform 工作空间项目结构

    我想设置 Terraform 来管理开发 阶段 产品环境 所有环境中的基础设施都是相同的 但每个环境中的变量都存在差异 既然 Terraform 0 10 中引入了工作区 那么理想的 Terraform 项目结构是什么样的 在命名 标记基础
  • PKCS5_PBKDF2_HMAC_SHA1返回值是什么意思?

    我正在尝试使用 OpenSSLPKCS5 PBKDF2 HMAC SHA1方法 我推测如果成功则返回 0 否则返回一些其他值 我的问题是 非零返回值是什么意思 内存错误 使用错误 我的程序应该如何处理它 重试 退出 编辑 一个必然的问题是
  • Android 上的鱿鱼:最大继承深度

    这是我的设置 声纳Qube 5 6 6 SonarJava插件4 8 0 9441 Code public class BaseActivity extends android app Activity public class FooAc
  • Pandas MultiIndex DataFrame.rolling 偏移量

    为什么我不能使用偏移量rolling多索引数据框 例如 与 rng pd date range 2017 01 03 periods 20 freq 8D i pd MultiIndex from product A B C rng nam
  • 优先考虑组合而不是继承[重复]

    这个问题在这里已经有答案了 优先考虑组合而不是继承 是非常流行的短语 我读了几篇文章 每篇文章最后都说 当类之间存在纯粹的 IS A 关系时 请使用继承 一个例子来自本文 这里之间Apple and Fruit存在明显的 IS A 关系 即
  • 如何告诉 Vite 从构建中排除目录中的文件子集?

    我使用创建了一个新的 Vue 应用程序npm create vue 在运行时 该应用程序会获取配置并从中读取字符串 该字符串表示要在应用程序内呈现的组件的名称 这些动态组件位于 可插入 目录中 src App vue pluggables
  • Cholesky 分解 ScaLapack 错误

    我收到以下错误 但我不知道为什么 1 1 On entry to PDPOTRF parameter number 2 had an illegal value 1 0 On entry to PDPOTRF parameter numbe
  • 具有依赖关系的静态库

    e exe与我的自定义静态库链接 c lib 它使用 Win32 API 中定义的w dll w dll位于C Windows System32 其导入库为w lib 位于 Windows SDK 目录中 壳w lib被列为额外的依赖 in
  • VS2022 17.2.0 Preview 2.0:访问项目等时出现T4模板序列化异常

    使用VS2022 17 2 0 Preview 2 0使用T4模板生成数据层 T4的一部分使用VS互操作 DTE来访问解决方案中的项目 下面的T4是一个测试 lt template debug false hostspecific true
  • 如何可视化 d3 力导向图布局中的节点组

    我正在寻找一种将组插入到我的力导向图形可视化中的方法 到目前为止我已经找到了三个相关的例子 Cola js这将需要添加另一个库 并可能需要改造我的代码以适应这个不同的库 这个街区 这很难解开 这张幻灯片来自 mbostock 的幻灯片 这不
  • Meteor:服务器端调试

    有谁知道调试服务器端代码的好方法 我尝试启用 Node js 调试 然后使用 node inspector 但它没有显示我的任何代码 我最终使用了 console log 但这非常低效 更新 我发现以下过程在我的 Linux 机器上有效 当
  • 从 Java 调用 python 模块

    我想使用 PythonInterpreter 从 Java 调用 python 模块中的函数 这是我的 Java 代码 PythonInterpreter interpreter new PythonInterpreter interpre
  • 默认情况下具有数学集合相等的集合类[关闭]

    Closed 这个问题需要多问focused 目前不接受答案 HashSet不将设置相等语义用于默认相等操作 var a new HashSet
  • 用于编辑页眉和页脚的 WORD 2010 宏

    我只有基本的 VBA 经验 之前的宏经验主要是使用 WORD 2003 录制宏用于获取 GoToFooter 或编辑页脚 菜单命令并允许后续编辑 在 WORD 2010 中 此命令 以及许多其他命令 不会 记录 到宏 但在记录模式下 我确实
  • 为什么这个径向渐变没有完成圆?

    我正在尝试使用径向渐变在作为单选按钮的圆形元素内创建边框 基本的 CSS 如下所示 我不明白为什么红色渐变不围绕圆圈的整个圆周 当白色色标接近 100 时 顶部 右侧 左侧和底部会出现红色间隙 为什么会发生这种情况 以及如何在仍然使用径向渐
  • 是 C 还是 C++?

    我需要在 cpp c 源文件中使用自然对数函数 现在 我当然可以通过快速的谷歌搜索和简单的库解决方案来做到这一点 但我有点困惑 在cplusplus dot com网站的reference cmath log 下有一个如何使用日志功能的示例
  • JDialog标题的字体大小

    如何设置 JDialog 标题的字体大小 我在极高分辨率的显示器 5 兆像素 上显示 JDialog 但对话框标题不清晰 我需要在每个对话框的基础上执行此操作 因为该应用程序是多显示器的 有些对话框出现在较低分辨率的显示器上 有些对话框出现
  • .NET xsd 导入器创建不可序列化的类

    我正在使用 NETXSD EXE导入器从 XSD 文件集合生成 C 类 当我尝试将其中一个类序列化为 XML 时 它失败了 无效操作异常 当我深入研究它时 我发现创建的类之一似乎是错误的 这是相关的 XSD 代码
  • 正确使用 JPA criteria API、Predicates 和 CriteriaQuery 的 where 方法

    我正在尝试测试 JPA 存储库 这是我的客户端 测试代码 Test public void testFindBoitesByMultiFieldWithIdentifiantSet BoiteDataOnDemand dod new Boi