Java Criteria API:如果[NOT]NULL,则选择表达式<;价值>;
我正在尝试将以下简单查询转换为JPA criteria API:Java Criteria API:如果[NOT]NULL,则选择表达式<;价值>;,java,jpa,criteria-api,Java,Jpa,Criteria Api,我正在尝试将以下简单查询转换为JPA criteria 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(tick
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\uuu.ticketId))
:如果ISNULL
类似于ISNOTNULL
(对于MySQL/MariaDB数据库),则问题在于没有否定criteriaBuilder.isNotNull(ticketAction.get(ticketAction\uuu.ticketId))
:但这将返回一个谓词
,而select语句只接受表达式
s表结构符合要求 结果: 最后,我使用了一个construtor查询,它接收
ticket\u action
的id
。在构造函数中有关于状态的决定:this.hasTicketAction=tickettactionid!=无效代码>
不是很令人满意,但很有效
谢谢大家发布您的答案您可以使用以下示例在选择表达式中生成is not null:
CriteriaQuery<Tuple> cq = entityManager.getCriteriaBuilder().createTupleQuery();
Root<Test> pet = cq.from(Test.class);
cq.multiselect(pet.get("id1").isNotNull(), pet.get("id2"));
CriteriaQuery cq=entityManager.getCriteriaBuilder().createTupleQuery();
根pet=cq.from(测试类);
cq.multiselect(pet.get(“id1”).isNotNull(),pet.get(“id2”);
我认为生成的查询将抛出一个查询语法异常,因为jpa/hibernate可能不支持在select表达式中使用is not null。如果是这种情况,那么一个可能的解决方案可能是将is not null放在where子句中。您可以在此处找到该情况的示例您可以使用以下示例在select表达式中生成is not null:
CriteriaQuery<Tuple> cq = entityManager.getCriteriaBuilder().createTupleQuery();
Root<Test> pet = cq.from(Test.class);
cq.multiselect(pet.get("id1").isNotNull(), pet.get("id2"));
CriteriaQuery cq=entityManager.getCriteriaBuilder().createTupleQuery();
根pet=cq.from(测试类);
cq.multiselect(pet.get(“id1”).isNotNull(),pet.get(“id2”);
我认为生成的查询将抛出一个查询语法异常,因为jpa/hibernate可能不支持在select表达式中使用is not null。如果是这种情况,那么一个可能的解决方案可能是将is not null放在where子句中。您可以在这里找到该案例的示例一种工作方法是使用CriteriaBuilder。选择case(…)
使用DTO
like(Object[]
也会这样做,但从一开始就是类型安全的)
可以通过以下查询获得结果
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")
);
将返回具有和不具有TicketAction
的票证的计数
我不知道实际的原因,但问题似乎在于cb.isNotNull(..)
(my)JPA
implementation要么总是获取看起来不为null的内容
要么根据检查null
的方式,它创建一些内部联接
,以便从结果集中删除null
值
(我正在使用OpenJPA)一种工作方法是使用CriteriaBuilder.selectCase(…)
使用DTO
like(Object[]
也会这样做,但从一开始就是类型安全的)
可以通过以下查询获得结果
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")
);
将返回具有和不具有TicketAction
的票证的计数
我不知道实际的原因,但问题似乎在于cb.isNotNull(..)
(my)JPA
implementation要么总是获取看起来不为null的内容
要么根据检查null
的方式,它创建一些内部联接
,以便从结果集中删除null
值
(我正在使用OpenJPA)对于此查询,您需要具有类型为的集合属性。
此外,我还必须使用而不是TicketTuple
(答案中引用),因为在处理没有票证的票证操作时,它给出了IllegalArgumentException
(参数类型不匹配),我不知道您的模式中是否存在这种可能性
EclipseLink JPA实现,Derby db
在classTicket
中,您必须具有以下属性:
@OneToMany(mappedBy = "ticket")
private Collection<TicketAction> ticketActions;
对于此查询,您需要具有类型为的集合属性。
此外,我还必须使用而不是TicketTuple
(答案中引用),因为在处理没有票证的票证操作时,它给出了IllegalArgumentException
(参数类型不匹配),我不知道您的模式中是否存在这种可能性
EclipseLink JPA实现,Derby db
在classTicket
中,您必须具有以下属性:
@OneToMany(mappedBy = "ticket")
private Collection<TicketAction> ticketActions;
可以看到您的实体吗<代码>@OneToOne
?还有3-4行,您期望的结果是什么?是不是像true,1:false,2;false,3,true:4
对于拉伸目标的分组方式
:有一个集合或什么分组?更新了我的答案。您是否可以按票证检查此分组。票证id不为NULL
?您的第二次进近描述错误isNotNull
返回一个谓词
,它实际上是一个表达式
,并且扩展了选择
。问题在于布尔泛型类型与CriteriaQuery泛型类型定义的内容冲突。也许如果您发布了查询构造的其余部分,那么它将是一个更完整的定义……是否有可能看到您的实体<代码>@OneToOne
?还有3-4行,您期望的结果是什么?是不是像true,1:false,2;false,3,true:4
对于拉伸目标的分组方式
:有一个集合或什么分组?更新了我的答案。您是否可以按票证检查此分组。票证id不为NULL
?您的第二次进近描述为w
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> cq = cb.createQuery(Tuple.class);
Root<Ticket> from = cq.from(Ticket.class);
Join<Ticket, TicketAction> join = from.join("ticketActions", JoinType.LEFT);
Expression<Boolean> caseHasAction = cb.<Boolean>selectCase()
.when(cb.isNotNull(join.get("id")), true)
.otherwise(false);
cq.multiselect(
caseHasAction.as(Boolean.class)
,from.get("id")
);
TypedQuery<Tuple> tq = em.createQuery(cq);
for (Tuple tt : tq.getResultList()) {
System.out.println("Res: " + tt.get(0) + " " + (tt.get(1) == null ? "null" : tt.get(1).toString()));
}
SELECT CASE WHEN (t0.ID IS NOT NULL) THEN 1 ELSE 0 END , t1.ID FROM TICKET t1 LEFT OUTER JOIN TICKET_ACTION t0 ON (t0.TICKET_ID = t1.ID)