I’m struggling with reusing a Specification<T> inside another one.
Entities:
Grouphas a list ofStudentGroupInfo.I already have a
Specification<Group>that can filterGroupby various conditions (joins, group by, having, etc.).Now I need to count all
StudentGroupInfofor the groups that are matched by thisSpecification<Group>.
Repository:
public interface StudentGroupInfoRepository extends JpaRepository<StudentGroupInfo, Long> {
long count(Specification<StudentGroupInfo> specification);
}
Attempt to reuse the group specification via subquery:
private Specification<StudentGroupInfo> buildSpecificationByGroupSpecification(
Specification<Group> groupSpecification) {
return (root, query, builder) -> {
var subquery = query.subquery(Long.class);
var groupRoot = subquery.from(Group.class);
// how to apply the groupSpecification here?
var groupPredicate = groupSpecification.toPredicate(groupRoot, query /* ??? */, builder);
subquery.select(groupRoot.get(BaseEntity.Fields.id))
.where(groupPredicate);
return root.get(StudentGroupInfo.Fields.group).in(subquery);
};
}
Problem:
If the groupSpecification is simple, it works.
But if it contains joins, group by or having, Hibernate throws:
Caused by: org.hibernate.sql.ast.SqlTreeCreationException: Could not locate TableGroup - com.sdx.rootservice.model.group.Group(...)
I assume it happens because I pass the outer query into groupSpecification.toPredicate(...), while that Specification expects a root from the main query, not from a subquery.
Question:
How can I properly reuse an existing Specification<Group> inside a subquery in another specification, or do I need a different approach for it (e.g. refactor to join instead of subquery)?