Java 使用jpa标准在另一个表中选择每个状态的出现次数
我需要在一个查询中使用CriteriaAPI选择我的主表和另一个表中每个状态的出现次数 我目前的解决方案是使用原生查询,这是可行的,但我想用一种更基于对象的方式来实现。 我尝试在criteria中使用特定的查询来选择所有状态,然后手动计数。但通过这种方法,我调用了两个查询:一个用于获取主表中的详细信息,另一个用于选择id与主表相同的所有状态。 有没有更有效的方法 以下是我的本机查询(简化): 这是我的CM实体(简化): 这是我的CM_参数实体(简化): 使用本机查询方法,我可以在我的Cm实体中添加临时字段:Java 使用jpa标准在另一个表中选择每个状态的出现次数,java,jpa,spring-data-jpa,criteria-api,Java,Jpa,Spring Data Jpa,Criteria Api,我需要在一个查询中使用CriteriaAPI选择我的主表和另一个表中每个状态的出现次数 我目前的解决方案是使用原生查询,这是可行的,但我想用一种更基于对象的方式来实现。 我尝试在criteria中使用特定的查询来选择所有状态,然后手动计数。但通过这种方法,我调用了两个查询:一个用于获取主表中的详细信息,另一个用于选择id与主表相同的所有状态。 有没有更有效的方法 以下是我的本机查询(简化): 这是我的CM实体(简化): 这是我的CM_参数实体(简化): 使用本机查询方法,我可以在我的Cm实体中添
@Transient
private Long countPending;
@Transient
private Long countFailed;
@Transient
private Long countProcessed;
我如何使用CriteriaAPI,如果可能的话,在一个事务中就可以做到这一点
预期的输出可能是这样的:
{
"idCm": 1,
"type": "sms",
"countPending": 5,
"countFailed": 3,
"countProcessed": 9
}
可以在不使用子查询联接的情况下重写查询:
SELECT
a.id_cm,
a.type
COUNT(CASE WHEN b.status = 'PENDING' THEN 1 ELSE NULL END) countPending,
COUNT(CASE WHEN b.status = 'FAILED' THEN 1 ELSE NULL END) countFailed,
COUNT( CASE WHEN b.status = 'PROCESSED' THEN 1 ELSE NULL END ) countProcessed
FROM CM AS a
LEFT JOIN CM_PARAM AS b ON a.id_cm = b.id_cm
WHERE a.id_cm = ?1
GROUP BY a.id_cm, a.type
您必须将关联的反面添加到Cm
:
@OneToMany(mappedBy = "cm")
private Set<CmParam> params;
请注意,结果的类型为Object[]
。如果您想使用当前方法处理瞬态字段,最简单的方法是将适当的构造函数添加到Cm
并使用cb.construct()
方法:
cq.select(cb.construct(Cm.class, a.get("idCm"), a.get("type"), ...))
请注意:
- 如果您不想将
字段添加到params
,但可以使用Cm
内部连接
,您只需使用
和根b=cq.from(CmParam.class)
李>连接a=b.JOIN(“Cm”)
- 如果在实际查询中,您从
中选择的属性多于Cm
和cmId
,您可能还需要在status
中列出它们groupBy
- 如果在实际查询中,您从
SELECT
a.id_cm,
a.type
COUNT(CASE WHEN b.status = 'PENDING' THEN 1 ELSE NULL END) countPending,
COUNT(CASE WHEN b.status = 'FAILED' THEN 1 ELSE NULL END) countFailed,
COUNT( CASE WHEN b.status = 'PROCESSED' THEN 1 ELSE NULL END ) countProcessed
FROM CM AS a
LEFT JOIN CM_PARAM AS b ON a.id_cm = b.id_cm
WHERE a.id_cm = ?1
GROUP BY a.id_cm, a.type
您必须将关联的反面添加到Cm
:
@OneToMany(mappedBy = "cm")
private Set<CmParam> params;
请注意,结果的类型为Object[]
。如果您想使用当前方法处理瞬态字段,最简单的方法是将适当的构造函数添加到Cm
并使用cb.construct()
方法:
cq.select(cb.construct(Cm.class, a.get("idCm"), a.get("type"), ...))
请注意:
- 如果您不想将
字段添加到params
,但可以使用Cm
内部连接
,您只需使用
和根b=cq.from(CmParam.class)
李>连接a=b.JOIN(“Cm”)
- 如果在实际查询中,您从
中选择的属性多于Cm
和cmId
,您可能还需要在status
中列出它们groupBy
- 如果在实际查询中,您从
cq.select(cb.construct(Cm.class, a.get("idCm"), a.get("type"), ...))