Spring Data JPA - 自定义查询结果中包含多个聚合函数

18

我试图在一次查询中返回一组评级的平均值和计数。我按照我在浏览时找到的示例,在两个查询中相对轻松地完成了它。例如:

@Query("SELECT AVG(rating) from UserVideoRating where videoId=:videoId")
public double findAverageByVideoId(@Param("videoId") long videoId);

但是当我想在同一个查询中获得平均值和计数时,问题就开始了。经过多个小时的尝试,我找到了这个可行的方法,现在在这里分享给大家。希望能对你有所帮助。

1)我需要为结果创建一个新的类:

然后我需要在查询中引用那个类:

@Query("SELECT new org.magnum.mobilecloud.video.model.AggregateResults(AVG(rating) as rating, COUNT(rating) as TotalRatings) from UserVideoRating where videoId=:videoId")
public AggregateResults findAvgRatingByVideoId(@Param("videoId") long videoId);

现在一个查询可以返回平均评级和评级数量。


这会填充其他属性吗? - Jef
2个回答

22

自己解决了。

自定义类以接收结果:

public class AggregateResults {

    private final double rating;
    private final int totalRatings;

    public AggregateResults(double rating, long totalRatings) {
        this.rating = rating;
        this.totalRatings = (int) totalRatings;
    }

    public double getRating() {
        return rating;
    }

    public int getTotalRatings() {
        return totalRatings;
    }
}

and
@Query("SELECT new org.magnum.mobilecloud.video.model.AggregateResults(
    AVG(rating) as rating, 
    COUNT(rating) as TotalRatings) 
    FROM UserVideoRating
    WHERE videoId=:videoId")
public AggregateResults findAvgRatingByVideoId(@Param("videoId") long videoId);

请定义您的自定义类。 - Garry
公共类AggregateResults { private final double rating; private final int totalRatings;public AggregateResults(double rating, long totalRatings) { this.rating = rating; this.totalRatings = (int) totalRatings; } public double getRating() { return rating; } public int getTotalRatings() { return totalRatings; }} - formica
谢谢...请将这个添加到您的答案中并联系 - Garry
你的自定义类标记为“Entity”了吗?我得到了“实体没有定义主键属性”的错误。 - jmhostalet
@jmhostalet 你需要在映射到表的类中使用 @Entity 注解,但不需要在自定义结果类中使用。你的错误听起来像是与映射到数据库表的类有关的问题。你需要在该类中的某个列上打上 @Id 标签。例如: @Id @GeneratedValue(strategy = GenerationType.AUTO) private long id; 抱歉,对话框不允许我输入“at”符号。 - formica
我在我的领域(模型)类中有一个多对一的关系,指向另一个领域类。我想将该对象添加到group by和select查询中。请问有人可以帮忙吗? - Shamseer

4

谢谢。

您应该按照以下方式预防NPE和Hibernate解析元组错误:

public class AggregateResults {

private final double rating;
private final int totalRatings;

public AggregateResults(Double rating, Long totalRatings) {
    this.rating = rating == null ? 0 : rating;
    this.totalRatings = totalRatings == null ? 0 : totalRatings.intValue();
}

public double getRating() {
    return rating;
}
public int getTotalRatings() {
    return totalRatings;
}}

是的,我猜AVG()可能会返回null,尽管如果没有匹配的行,则COUNT()将为0。 - formica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接