当前位置: 首页 > 知识库问答 >
问题:

JPA CriteriaBuilder多通和空值

冯野
2023-03-14

我试图创建一个用于过滤表的规范。这个表有2个manytone关系(可以为null),我想在其中应用过滤器。就像一个搜索功能。

假设此结构

public class X {
   @ManyToOne(targetEntity = A.class, fetch = FetchType.EAGER)
   @JoinColumn(nullable = true, name = "aID")
   private A a;

   @ManyToOne(targetEntity = B.class, fetch = FetchType.EAGER)
   @JoinColumn(nullable = true, name = "bID")
   private B b;
}

还假设A和B有一个名为name的属性。

那么,我想为X做一个规范,在这里我可以在a或B的名称中匹配一个字符串。

这是我的方法:

public static Specification<X> filterName(String value) {
   return new Specification<X>() {
      public Predicate toPredicate(Root<X> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
    
         Expression<String> aName = root.get("a").get("name").as(String.class);
         Expression<String> bName = root.get("b").get("name").as(String.class);

         List<Predicate> predicates = new ArrayList<>();

         if (!value.isEmpty()) {
            predicates.add(builder.like(aName, "%" + value + "%"));
            predicates.add(builder.like(bName, "%" + value + "%"));
         }else{
            return null;
         }

         Predicate predicate = builder.or(predicates.toArray(new Predicate[0]));
         return predicate;
      }
   };
}

我真的希望它能起作用,但没有。

我想要的是显示那些行,其中A的名称或B的名称是类似于输入值的。

如果我启用日志来显示SQL查询,我会得到以下结果:

选择xentity0_。援助,xentity0_。来自表x xtab cross join table\u a atab cross join table\u b btab的投标,其中xtab.aId=atab。id和xtab。bId=btab。id和(atab.name like?)和(btab.name like?)

我认为问题在于其中xtab.aId=atab。id和xtab。bId=btab。id部分。因为asAB可以为空,所以并不总是满足该条件。

假设此表适用于X

此表适用于A:

B的此表:

使用X规范查找%Lu%时,我希望看到的是

因为Lucy在A中,Luke在B中。相反,我看到的是最后一行(其中A和B都不是null)

共有1个答案

萧飞
2023-03-14

问题是,CriteriaBuilder默认使用交叉连接(您提到的关于BTW的内容)。这就是它无法获取ABnull的数据的原因。您可以通过将Jointype设置为LEFT来获取这些记录:

root.join(Entity.childEntity, JoinType.LEFT)

在您的情况下,请尝试按以下方式修改代码:

Expression<String> aName = root.join("a", JoinType.LEFT).get("name").as(String.class);
Expression<String> bName = root.join("b", JoinType.LEFT).get("name").as(String.class);

除此之外,我建议对标准生成器使用元模型。

要不手动创建和维护Metamodel类,您可以使用可用的生成器之一,例如Hibernate JPA Metamodel GeneratorOpenJPAEclipse LinkDataNcore us

我个人更喜欢Hibernate JPA 2元模型生成器。要使用它,您唯一需要做的就是将依赖项添加到pom。xml文件:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-jpamodelgen</artifactId>
    <version>5.6.5.Final</version>
    <scope>provided</scope>
</dependency>

以及注释处理器路径下的以下代码:

 <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
      <annotationProcessorPaths>
        <path>
          <groupId>org.hibernate</groupId>
          <artifactId>hibernate-jpamodelgen</artifactId>
          <version>5.6.5.Final</version>
        </path>
      </annotationProcessorPaths>
    </configuration>
  </plugin>

之后,当您使用Maven构建应用程序时,将自动构建所有实体的元模型。

 类似资料:
  • 前面两节里我们用到的输入和输出都是二维数组,但真实数据的维度经常更高。例如,彩色图像在高和宽2个维度外还有RGB(红、绿、蓝)3个颜色通道。假设彩色图像的高和宽分别是$h$和$w$(像素),那么它可以表示为一个$3\times h\times w$的多维数组。我们将大小为3的这一维称为通道(channel)维。本节我们将介绍含多个输入通道或多个输出通道的卷积核。 多输入通道 当输入数据含多个通道时

  • 问题内容: 我有一个Node.js Web服务器,该服务器在顶部运行套接字服务器,该服务器是使用Socket.io创建的。基本上,这可行。 我现在想要实现的是将连接的客户端按组进行群集。所以可能有一些客户从而弥补了A组和其他一些客户从而弥补了B组,他们将选择哪个组由他们一adressing特定的URL,无论是属于或。 现在,在Socket.io中,我希望将消息发送到A组中的所有客户端或B组中的所有

  • 本文向大家介绍java Split 实现去除一个空格和多个空格,包括了java Split 实现去除一个空格和多个空格的使用技巧和注意事项,需要的朋友参考一下 用Split函数可以去除输入一个字符串中的空格,并且一般都是将它存储在一个字符串数组之中 例如: 输出结果是: 0 1 2 3 4 3 可是会出现这种情况,如果我输入的是0 1 2 3 4,在2和3之间有3个的空格,那还会有用吗? 结果输出

  • 我对Postgres Unique约束有问题,该约束包含多个可能包含空值的列。 让我们假设这种情况: Insert将插入('foo',bar')一次和('foo',NULL)两次(尽管直觉告诉它应该插入一次)。 在这种情况下,解决方案非常简单。我可以添加唯一的索引 但是当有更多的列和不同的类型(不仅仅是文本)时,问题就开始了。假设我们有10列,其中9列可以有值。也许我可以用大量的限制来解决它,但这

  • 我有一个多线程应用程序,它将传入的消息发布到rabbitmq交换。使用rabbitmq java客户端,我在应用程序启动时创建一个rabbitmq连接,并在所有线程之间共享它。每个线程都创建一个新通道(threadlocal),这样通道就不会像rabbitmq文档所建议的那样在多个线程之间共享。我正在使用netty,我看到相同数量的rabbitmq通道被创建为netty通道管道线程。到目前为止还不

  • 本文向大家介绍php通过各种函数判断0和空,包括了php通过各种函数判断0和空的使用技巧和注意事项,需要的朋友参考一下 函数对0的判断 对空的判断 补充:下面给大家介绍下php 语法里0不等于null为空的解决办法 今天遇到这样一个问题是这样的: php 语句里,我想判断一个值大于等于0. 我是使用 ($value !=null && $value >=0), 返回的结果为空,这点真的好奇怪。 实