java - 标准 API : Select Expression IF [NOT] NULL <value>

标签 java jpa criteria-api

我正在尝试将以下简单查询转换为 JPA 标准 API:

SELECT ticket_action.ticket_id IS NOT NULL, ticket.id
FROM ticket
LEFT OUTER JOIN ticket_action ON ticket.id = ticket_action.ticket_id

我尝试了两种方法:

  1. 使用 criteriaBuilder.function("ISNULL", Boolean.class, ticketAction.get(TicketAction_.ticketId)):问题是如果 ISNULLISNOTNULL(对于 MySQL/MariaDB 数据库)
  2. 使用 criteriaBuilder.isNotNull(ticketAction.get(TicketAction_.ticketId)):但这会返回一个 Predicate 而 select 语句只接受 Expressions

拉伸(stretch)目标:与 GROUP BY ticket.ticket_id IS NOT NULL 相同


请求的表结构

+-----------+---------+
|         ticket      |
+-----------+---------+
|   name    |  type   |
+-----------+---------+
| id        | integer |
| title     | varchar |
+-----------+---------+

+-----------+---------+
|    ticket_action    |
+-----------+---------+
|   name    |  type   |
+-----------+---------+
| id        | integer |
| ticket_id | integer |
| title     | varchar |
+-----------+---------+

结果:

最后,我最终使用了一个构造器查询,它接收 ticket_actionid 等。在构造函数中有关于状态的决定:this.hasTicketAction = ticketActionId != null; 不是很满意,但工作。

感谢任何人发布您的答案!

最佳答案

一种可行的方法是使用 CriteriaBuilder.selectCase(..)

使用 DTO 就像(Object[] 做同样的事情,但这从一开始就是类型安全的)

@Getter
@AllArgsConstructor
public class TicketTuple {
   private Boolean hasAction;
   private Long ticketId;
}

可以通过以下查询得到结果

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<TicketTuple> cq = cb.createQuery(TicketTuple.class);
Root<Ticket> from = cq.from(Ticket.class);
Join<Ticket, TicketAction> join = from.join("ticketAction", JoinType.LEFT);

Expression<Boolean> caseHasAction = cb.<Boolean>selectCase()
      .when(cb.isNotNull(join), true)
      .otherwise(false);

cq.multiselect(
      caseHasAction.as(Boolean.class)
     ,from.get("id")
);

关于分组,我不太明白你需要分组什么,但是举个例子

cq.multiselect(
     caseHasAction.as(Boolean.class)
     ,cb.count(from.get("id"))
).groupBy(caseHasAction.as(Boolean.class));

将返回具有和不具有 TicketActionTicket 的计数。

我不知道真正的原因,但问题似乎是 cb.isNotNull(..) (my) JPA实现 either 总是获取似乎不是 null 的内容,具体取决于检查 null 的方式创建一些 INNER JOIN 以便从结果集中删除 null 值。

(我正在使用 OpenJPA)

关于java - 标准 API : Select Expression IF [NOT] NULL <value>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47830390/

相关文章:

java - 在 JPQL 中,是否可以将列表作为参数写入 "select new"?

java - 如何重命名列名称 - JPA Hibernate

java - 构建 CriteriaBuilder 查询来比较列表

java - 在 JPA Criteria API 查询中使用 countDistinct 的示例

java - 为什么我的代码只执行一次

java - 如何在 JLabel 和 Jext Boxes java swing 中从属性文件动态显示数据而不知道属性文件中的数据

java - 不保存子实体

java - 如何使用JPA Criteria根据EmbeddedId的字段进行查询?

java - 在数据库中初始化不可变的 JPA 集合

java - 当我的编译器告诉我正在使用不安全或未经检查的操作时,这意味着什么?