JPA 标准 API - 对 GROUP BY 进行空检查
JPA Criteria API - null check on GROUP BY
我需要 return 结果数组,其中分组列中的数据可能包含空值,目前已跳过这些值,而我也希望将它们分组。
我的实体:
public class UserEntity {
// ...
@Basic
@Column(name = "username")
private String username;
}
public class ZgloszenieEntity {
// ...
@ManyToOne
@JoinColumn(name = "assigned_user_id" )
@OrderBy("username")
private UserEntity assignedUser;
@ManyToOne(targetEntity = InternalStatusEntity.class)
@JoinColumn(name = "internal_status")
@NotAudited
private InternalStatusEntity internalStatus;
}
受影响的代码:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<EfficiencyStatusReportDTO> cq = cb.createQuery(EfficiencyStatusReportDTO.class);
Root<ZgloszenieEntity> root = cq.from(ZgloszenieEntity.class);
Join<UserEntity, ZgloszenieEntity> join = root.join("assignedUser");
cq.multiselect(join.get("username")
, root.get("internalStatus").get("description")
, getNumberOfDocOfType(cb, root, "X-1")
, getNumberOfDOcOfType(cb, root, "X-2")
, getNumberOfDocOfType(cb, root, "X-3")
, getNumberOfDocOfType(cb, root, "X-4")
, cb.count(root)
);
cq.groupBy(join.get("username"), root.get("internalStatus").get("description"));
它适用于具有 internalStatus != null 的实体,但也可以在没有连接的 InternalStatus 的情况下使用它,然后我想将它按 null 分组。
当前示例结果:
// ...
{
"username": "admin@gmail.com",
"internalStatus": "Do stuff",
"numberOfDoc1": 0,
"numberOfDoc2": 2,
"numberOfDoc3": 1,
"numberOfDoc4": 0,
"sumOfDoc": 3
},
而且我希望它也有这样的结果:
{
"username": "admin@gmail.com",
"internalStatus": null,
"numberOfDoc1": 4,
"numberOfDoc2": 1,
"numberOfDoc3": 5,
"numberOfDoc4": 0,
"sumOfDoc": 10
},
JPA 生成的查询:
select userentity1_.username as col_0_0_,
internalst2_.description as col_1_0_,
count(case when zgloszenie0_.form_type='X-1' then 1 else null end) as col_2_0_,
count(case when zgloszenie0_.form_type='X-2' then 1 else null end) as col_3_0_,
count(case when zgloszenie0_.form_type='X-3' then 1 else null end) as col_4_0_,
count(case when zgloszenie0_.form_type='X-4' then 1 else null end) as col_5_0_,
count(zgloszenie0_.uid) as col_6_0_
from zgloszenie zgloszenie0_
inner join user userentity1_ on zgloszenie0_.assigned_user_id = userentity1_.id
cross join internal_status internalst2_
where zgloszenie0_.internal_status = internalst2_.id
and 1 = 1
group by userentity1_.username, internalst2_.description
order by userentity1_.username desc
有没有办法更改自动创建的交叉连接以考虑空值?
试试这个
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<EfficiencyStatusReportDTO> cq =
cb.createQuery(EfficiencyStatusReportDTO.class);
Root<ZgloszenieEntity> root = cq.from(ZgloszenieEntity.class);
Join<ZgloszenieEntity, UserEntity> assignedUser = root.join("assignedUser",
JoinType.LEFT);
Join<ZgloszenieEntity, InternalStatus> internalStatus = root.join("internalStatus",
JoinType.LEFT);
cq.multiselect(assignedUser.get("username"),
internalStatus.get("description"),
getNumberOfDocOfType(cb, root, "X-1"),
getNumberOfDOcOfType(cb, root, "X-2"),
getNumberOfDocOfType(cb, root, "X-3"),
getNumberOfDocOfType(cb, root, "X-4"),
cb.count(root)
);
cq.groupBy(assignedUser.get("username"), internalStatus.get("description"));
我需要 return 结果数组,其中分组列中的数据可能包含空值,目前已跳过这些值,而我也希望将它们分组。
我的实体:
public class UserEntity {
// ...
@Basic
@Column(name = "username")
private String username;
}
public class ZgloszenieEntity {
// ...
@ManyToOne
@JoinColumn(name = "assigned_user_id" )
@OrderBy("username")
private UserEntity assignedUser;
@ManyToOne(targetEntity = InternalStatusEntity.class)
@JoinColumn(name = "internal_status")
@NotAudited
private InternalStatusEntity internalStatus;
}
受影响的代码:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<EfficiencyStatusReportDTO> cq = cb.createQuery(EfficiencyStatusReportDTO.class);
Root<ZgloszenieEntity> root = cq.from(ZgloszenieEntity.class);
Join<UserEntity, ZgloszenieEntity> join = root.join("assignedUser");
cq.multiselect(join.get("username")
, root.get("internalStatus").get("description")
, getNumberOfDocOfType(cb, root, "X-1")
, getNumberOfDOcOfType(cb, root, "X-2")
, getNumberOfDocOfType(cb, root, "X-3")
, getNumberOfDocOfType(cb, root, "X-4")
, cb.count(root)
);
cq.groupBy(join.get("username"), root.get("internalStatus").get("description"));
它适用于具有 internalStatus != null 的实体,但也可以在没有连接的 InternalStatus 的情况下使用它,然后我想将它按 null 分组。
当前示例结果:
// ...
{
"username": "admin@gmail.com",
"internalStatus": "Do stuff",
"numberOfDoc1": 0,
"numberOfDoc2": 2,
"numberOfDoc3": 1,
"numberOfDoc4": 0,
"sumOfDoc": 3
},
而且我希望它也有这样的结果:
{
"username": "admin@gmail.com",
"internalStatus": null,
"numberOfDoc1": 4,
"numberOfDoc2": 1,
"numberOfDoc3": 5,
"numberOfDoc4": 0,
"sumOfDoc": 10
},
JPA 生成的查询:
select userentity1_.username as col_0_0_,
internalst2_.description as col_1_0_,
count(case when zgloszenie0_.form_type='X-1' then 1 else null end) as col_2_0_,
count(case when zgloszenie0_.form_type='X-2' then 1 else null end) as col_3_0_,
count(case when zgloszenie0_.form_type='X-3' then 1 else null end) as col_4_0_,
count(case when zgloszenie0_.form_type='X-4' then 1 else null end) as col_5_0_,
count(zgloszenie0_.uid) as col_6_0_
from zgloszenie zgloszenie0_
inner join user userentity1_ on zgloszenie0_.assigned_user_id = userentity1_.id
cross join internal_status internalst2_
where zgloszenie0_.internal_status = internalst2_.id
and 1 = 1
group by userentity1_.username, internalst2_.description
order by userentity1_.username desc
有没有办法更改自动创建的交叉连接以考虑空值?
试试这个
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<EfficiencyStatusReportDTO> cq =
cb.createQuery(EfficiencyStatusReportDTO.class);
Root<ZgloszenieEntity> root = cq.from(ZgloszenieEntity.class);
Join<ZgloszenieEntity, UserEntity> assignedUser = root.join("assignedUser",
JoinType.LEFT);
Join<ZgloszenieEntity, InternalStatus> internalStatus = root.join("internalStatus",
JoinType.LEFT);
cq.multiselect(assignedUser.get("username"),
internalStatus.get("description"),
getNumberOfDocOfType(cb, root, "X-1"),
getNumberOfDOcOfType(cb, root, "X-2"),
getNumberOfDocOfType(cb, root, "X-3"),
getNumberOfDocOfType(cb, root, "X-4"),
cb.count(root)
);
cq.groupBy(assignedUser.get("username"), internalStatus.get("description"));