首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JPQL查询按平均评级排序,然后按电影票房值排序

JPQL查询按平均评级排序,然后按电影票房值排序
EN

Stack Overflow用户
提问于 2022-01-10 08:33:06
回答 1查看 233关注 0票数 1

好的,我有两个JPA实体,一个电影和一个MovieRating。如下所示

代码语言:javascript
复制
@Entity
@Table(name = Movie.TABLE_NAME)
public class Movie {

    static final String TABLE_NAME = "Movies";

    @Id
    @Column(name = "IMDB_ID")
    private String imdbID;

    @Column(name = "BOX_OFFICE_TAKINGS")
    private int boxOfficeTakings;

    @OneToMany(mappedBy = "movie", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<MovieRating> ratings = new ArrayList<>();

    // Getters and setters

}

代码语言:javascript
复制
@Entity
@Table(name = MovieRating.TABLE_NAME)
public class MovieRating {

    static final String TABLE_NAME = "MovieRatings";

    @Id
    @GeneratedValue(generator = "UUID")
    @GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
    private UUID id;

    private int rating;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "IMDB_ID")
    private Movie movie;

    //Getters and setters
}

我在JPA中写了一个@Query,它应该返回按平均评级降序的结果,然后按票房值下降,例如。

代码语言:javascript
复制
@Query("SELECT m FROM Movie m LEFT JOIN m.ratings r GROUP BY m ORDER BY AVG(r.rating) desc, m.boxOfficeTakings desc")
List<Movie> findTop10OrderedByBoxOfficeTakings(Pageable pageable);

例如,我希望一部票房值较低的电影出现在一部票房值较高的未评级电影之上。

所以我已经写了一个测试,它似乎像我所期望的那样起作用

代码语言:javascript
复制
@Test
public void testGetTop10ReturnsRatedMovieAboveUnratedMovieWithHigherValue() {
    Movie movie1 = createMovieWithRatings(new Movie("tt000001", "The Godfather part 1", 2010, 268500000), null);
    Movie movie2 = createMovieWithRatings(new Movie("tt000002", "The Godfather part 2", 2010, 93000000),
            Arrays.asList(new MovieRating(10)));
    
    movieRepository.saveAll(Arrays.asList(movie1, movie2));
    
    List<MovieResponse> top10 = movieService.getTop10OrderedByBoxOfficeTakings();
    
    List<String> expectedMovieIds = Arrays.asList(movie2.getImdbID(), movie1.getImdbID());

    List<String> actualMovieIds = top10.stream().map(movie -> movie.getImdbID()).collect(Collectors.toList());

    Assertions.assertEquals(expectedMovieIds, actualMovieIds);
}

private Movie createMovieWithRatings(Movie movie, List<MovieRating> ratings) {
    if (ratings != null) {
        ratings.forEach(rating -> movie.addRating(rating));
    }
    return movie;
}

然而,在实践中,当代码运行时,顺序是movie1,然后是movie2。只有当Movie2收到超过一个等级时,它才会在movie1之上移动。为什么?

EN

回答 1

Stack Overflow用户

发布于 2022-01-10 17:15:19

也许是因为你在做一个左连接,如果没有值的话,你想要加入的任何东西,在你的例子中,“教父第1部分”没有任何评级,所以它是空的。尝试在查询本身中放置一个空检查,如果它是空替换为0,那么现在它可以计算每个电影的AVG。也许能帮上忙。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70649647

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档