Sql Spring数据:JPA存储库返回映射而不是列表?

Sql Spring数据:JPA存储库返回映射而不是列表?,sql,spring,spring-boot,jpa,spring-data-jpa,Sql,Spring,Spring Boot,Jpa,Spring Data Jpa,我有这样的疑问,我想从哪里提取电影的标题和评级 @Query(value ="SELECT m.title, avg(r.rating) " + "FROM movies m " + "INNER JOIN " + "ratings r " + "ON m.movieid = r.movieid " + &quo

我有这样的疑问,我想从哪里提取电影的标题和评级

   @Query(value ="SELECT m.title, avg(r.rating) " +
        "FROM movies m " +
        "INNER JOIN " +
        "ratings r " +
        "ON m.movieid = r.movieid " +
        "WHERE m.genres LIKE %:genre% " +
        "GROUP BY m.title " +
        "ORDER BY avg(r.rating) DESC " +
        "LIMIT 10",
        nativeQuery = true)
 List<Movies> topTenMoviesByGenreLikeIgnoreCase(@Param("genre") String genre);
试试这个:

@Query(value ="SELECT m.title as title, r.avg(rating) as rates " +
    "FROM movies m " +
    "INNER JOIN " +
    "ratings r " +
    "ON m.movieid = r.movieid " +
    "WHERE m.genre = LIKE %:genre% " +
    "GROUP BY r.avg(rating) " +
    "ORDER BY r.avg(rating) DESC " +
    "LIMIT 10",
    nativeQuery = true)

List<Movies> topTenMoviesByGenreLikeIgnoreCase(@Param("genre") String genre);    



default Map<Movies, Set<Ratings>> topTenMoviesByGenreLikeIgnoreCaseMap(@Param("genre") String genre) {
    return topTenMoviesByGenreLikeIgnoreCase(genre).stream().collect(
                                                            Collectors.toMap(
                                                            tuple -> (tuple.getTitle(),
                                                            tuple -> (tuple.getRates())
                                                         ));
}
@Query(value=“选择m.title作为标题,选择r.avg(评级)作为费率”+
“来自电影m”+
“内部联接”+
“评级r”+
“在m.movieid=r.movieid上”+
“其中m.genre=LIKE%:genre%”+
“按r.avg分组(评级)”+
“按r.avg(评级)说明订购”+
“限制10”,
nativeQuery=true)
列出TopTenMoviesByGenReliekeIgnorecase(@Param(“流派”)字符串流派);
默认映射TopTenMoviesByGenReliekeIgnoreCemap(@Param(“流派”)字符串流派){
返回TopTenMoviesByGenReliekeignoreCase(流派).stream().collect(
汤姆(
tuple->(tuple.getTitle(),
tuple->(tuple.getRates())
));
}

您可以通过这种方式使用
对象[]
作为查询结果

@Query(value ="SELECT m.title, avg(r.rating) " +
        "FROM movies m " +
        "INNER JOIN " +
        "ratings r " +
        "ON m.movieid = r.movieid " +
        "WHERE m.genres LIKE %:genre% " +
        "GROUP BY m.title " +
        "ORDER BY avg(r.rating) DESC " +
        "LIMIT 10",
        nativeQuery = true)
 List<Object[]> topTenMoviesByGenreLikeIgnoreCase(@Param("genre") String genre);
@Query(value=“选择m.title,平均(r.rating)”+
“来自电影m”+
“内部联接”+
“评级r”+
“在m.movieid=r.movieid上”+
“其中m.流派如%:流派%”+
“按m.title分组”+
“按平均(额定)说明订购”+
“限制10”,
nativeQuery=true)
列出TopTenMoviesByGenReliekeIgnorecase(@Param(“流派”)字符串流派);
那么

default Map<String, Float> topTenMoviesByGenreLikeIgnoreCaseMap(@Param("genre") String genre) {
    return topTenMoviesByGenreLikeIgnoreCase(genre)
            .stream()
            .collect(Collectors.toMap((arr->arr[0].toString()), (arr->Float.valueOf(arr[1].toString()))));
}
默认映射ToptenMoviesByGenReliekeIgnoreCemap(@Param(“流派”)字符串流派){
返回TopTenMoviesByGenReliekeIgnoreCase(流派)
.stream()
.collect(Collectors.toMap((arr->arr[0].toString()),(arr->Float.valueOf(arr[1].toString()));
}

如您所见,TopTenMoviesByGenReliekeIgnoreCemap返回电影标题所在的
Map
键。要使
电影
实体成为键,您应该使用
JPQL
查询,而不是本机查询。

我解释了您的建议,但似乎有一些小错误。
收集(.Collectors.toMap(.tuple
。顺便问一下,tuple是什么,从哪里获得的?另外,在我的例子中,tuple没有方法get()
tuple
被定义为SELECT查询生成的表的一行。很抱歉,tuple仍然没有get()此外,如果应用
toString()
floatValue()
,为什么要将所有内容转换为字符串?我假设将Float存储为一个值,如果我们将它稍微更改为
tuple->(tuple.getTitle()),我不需要将它转换为String
mb没关系,我们不需要强制转换字符串,但是
tuple->(tuple.get(“ratings”).floatValue()呢
?由于输出是Movies类,我无法获得电影的评级,因为它存储在其他类oop中,我也错过了。谢谢你的建议。我向你介绍了有关查询的注释。它写得非常精巧。我已将评级类添加到问题中。你介意解释一下什么是
JPQL
查询以及如何查询吗在我的情况下使用它?当我使用你的解决方案时,我得到了
所需的类型:Map提供:Map
。是否应该将其更改为
Map
,然后转换为
String,Float
?这是对的。这是我的错。必须转换类型
JPQL
用于对实体而不是数据库表进行查询。
ORM
可以基于
JPQL
query生成
SQL
query如果我像那样将其转换为
Collectors.toMap((arr->(String)arr[0]),(arr->(Float)arr[1]))
我看到将“arr[0]”转换为“String”是多余的,而转换为“arr[1]'到'浮动'是多余的。稍晚一点,我将尝试您的解决方案,并回复是否可行,并接受您的回答。我已编辑了您的答案。它与此类铸造完美配合。感谢您的帮助并注意到奇怪的查询方面
@Entity
public class Ratings {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer rateid;

@ManyToOne
@JoinColumn(name = "movieid")
private Movies movieid;

@ManyToOne
@JoinColumn(name = "userid")
private Usrs userid;

private float rating;
private Integer timestamp;

public Ratings() {
}

public Ratings(Movies movieid, Usrs userid, float rating, Integer timestamp)
{
    this.movieid = movieid;
    this.userid = userid;
    this.rating = rating;
    this.timestamp = timestamp;
}
/*Getters and Setters for variables*/
}
@Query(value ="SELECT m.title as title, r.avg(rating) as rates " +
    "FROM movies m " +
    "INNER JOIN " +
    "ratings r " +
    "ON m.movieid = r.movieid " +
    "WHERE m.genre = LIKE %:genre% " +
    "GROUP BY r.avg(rating) " +
    "ORDER BY r.avg(rating) DESC " +
    "LIMIT 10",
    nativeQuery = true)

List<Movies> topTenMoviesByGenreLikeIgnoreCase(@Param("genre") String genre);    



default Map<Movies, Set<Ratings>> topTenMoviesByGenreLikeIgnoreCaseMap(@Param("genre") String genre) {
    return topTenMoviesByGenreLikeIgnoreCase(genre).stream().collect(
                                                            Collectors.toMap(
                                                            tuple -> (tuple.getTitle(),
                                                            tuple -> (tuple.getRates())
                                                         ));
}
@Query(value ="SELECT m.title, avg(r.rating) " +
        "FROM movies m " +
        "INNER JOIN " +
        "ratings r " +
        "ON m.movieid = r.movieid " +
        "WHERE m.genres LIKE %:genre% " +
        "GROUP BY m.title " +
        "ORDER BY avg(r.rating) DESC " +
        "LIMIT 10",
        nativeQuery = true)
 List<Object[]> topTenMoviesByGenreLikeIgnoreCase(@Param("genre") String genre);
default Map<String, Float> topTenMoviesByGenreLikeIgnoreCaseMap(@Param("genre") String genre) {
    return topTenMoviesByGenreLikeIgnoreCase(genre)
            .stream()
            .collect(Collectors.toMap((arr->arr[0].toString()), (arr->Float.valueOf(arr[1].toString()))));
}