我正在尝试将以下简单查询转换为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


我尝试了两种方法:


使用criteriaBuilder.function("ISNULL", Boolean.class, ticketAction.get(TicketAction_.ticketId)):如果像ISNULL这样的ISNOTNULL(对于MySQL / MariaDB数据库),问题是没有否定的
使用criteriaBuilder.isNotNull(ticketAction.get(TicketAction_.ticketId)):但这将返回Predicate,而select语句仅接受Expression


伸展目标:与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 |
+-----------+---------+


结果:

最后,我最终使用了构造器查询,该查询接收了idticket_action。在构造函数中,有关于状态的决定: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));


将返回具有和不具有TicketTicketAction个计数。

我不知道实际的原因,但是问题似乎是通过cb.isNotNull(..)(我的)JPA实现要么总是获取似乎不是null的东西,要么取决于null的检查方式创建一些INNER JOIN,以便将null值从结果集中删除。

(我正在使用OpenJPA)

关于java - 条件API:选择表达式IF [NOT] NULL <值>,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47830390/

10-10 19:10