简体   繁体   中英

Using join fetch and group by in HQL query

I have a Report entity that has a list of ReportedTime as @OneToMany relation. Each ReportedTime has a project, and Project has a manager.

The query itself (shown at the bottom) works fine. The problem is I need to now map these entities to DTOs and for that mapping purpose I need to know the projects that are in each ReportedTime in each Report . So I'm facing an n+1 problem, and I wanted to join fetch the reportedTimes and projects:

 @Query(value = "select " +
            "t as timesheetReport, " +
            "FUNCTION('string_agg', tlpa.username, ',') as projectManagersUsernames, " +
            "case when " +
            "   FUNCTION('string_agg', tlpa.username, ',') like concat('%', :username, '%') " +
            "then true else false " +
            "end as assigned " +
            "from TimesheetReport t " +
            "left join fetch t.reportedTimes rt " +
            "left join fetch rt.project p " +
            "left join p.teamLeaderAssignments tlp " +
            "left join tlp.account tlpa " +
            "group by t " +
            "having sum(rt.workTime)>0 " +
            "order by assigned desc ")
    List<IReportWithManagers> findAllWithManagers(String username, Pageable pageable);

but I get this error:

org.postgresql.util.PSQLException: ERROR: column "reportedtimes1_.id" must appear in the GROUP BY clause or be used in an aggregate function

I tried to see the sql query in the logs and it seems that in this scenario Hibernate also puts the reported_time.id and project.id in the select clause but does not know how to group it? Is there way around this?

You're getting the error because, of course, when fetching the joined entities, you're suddenly attempting to select a whole bunch of new columns that are neither included in GROUP BY nor aggregated.

To be able to select columns from rt and p , you would need to GROUP BY t, rt, p , which unfortunately (as far as I understand) changes the semantics of the query. I'd try adding separate JOINS for fetching and grouping:

left join t.reportedTimes rt
left join rt.project p
left join fetch t.reportedTimes rt2
left join fetch rt.project p2
left join p.teamLeaderAssignments tlp
left join tlp.account tlpa
group by t, rt2, p2
having sum(dt.workTime)>0
order by assigned desc

The problem with the above is, duplicate rows will now enter the aggregation, so perhaps you could use ARRAY_TO_STRING(ARRAY_AGG(DISTINCT tlpa.username, ',') or select the array and join the strings in Java (not sure if Hibernate supports selecting PostgreSQL arrays out of the box, though, you'd need to check).

Please be advised that I haven't tried the above solution, so I cannot guarantee it will work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM