在HQL查询中使用join fetch和group by



我有一个Report实体,它有一个作为@OneToMany关系的ReportedTime列表。每个ReportedTime有一个项目,Project有一个经理。

查询本身(显示在底部(运行良好。问题是,我现在需要将这些实体映射到DTO,为此,我需要知道每个ReportedTimeReport中的项目。所以我面临一个n+1的问题,我想加入fetchedTimes和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);

但我得到了这个错误:

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

我试着在日志中查看sql查询,在这种情况下,Hibernate似乎也将reported_time.id和project.id放在了select子句中,但不知道如何对其进行分组?有办法绕过这个吗?

您之所以会出现错误,当然是因为在获取连接的实体时,您突然试图选择一大堆既不包含在GROUP BY中也不聚合的新列。

为了能够从rtp中选择列,您需要GROUP BY t, rt, p,不幸的是(据我所知(这会更改查询的语义。我会尝试添加单独的JOINS来获取和分组:

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

上面的问题是,重复的行现在会进入聚合,所以也许你可以使用ARRAY_TO_STRING(ARRAY_AGG(DISTINCT tlpa.username, ','),或者在Java中选择数组并连接字符串(不确定Hibernate是否支持开箱即用地选择PostgreSQL数组,但你需要检查(。

请注意,我还没有尝试过上述解决方案,所以我不能保证它会起作用。