Hibernate一对多关系:根据userId查询用户收藏的TvShow列表
问题分析与解决方案
你的问题主要出在实体关系映射错误和JPQL查询逻辑错误两个地方,咱们一步步来修正:
1. 修正实体类的关联关系
首先,User类中的@OneToMany注解的mappedBy参数写错了——它应该指向TvShow实体中关联User的属性名,而不是tvShowId。而且你目前的TvShow实体完全没有和User建立关联,这是一对多关系的核心缺失:
修正后的User.java
@Entity @Table(name = "users") public class User { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "user_id", updatable = false, nullable = false) private int userId; // mappedBy指向TvShow中的user属性 @OneToMany(mappedBy = "user", fetch = FetchType.EAGER) private List<TvShow> favourites; // 别忘了添加getter方法 public List<TvShow> getFavourites() { return favourites; } }
修正后的TvShow.java
需要添加@ManyToOne注解来关联User,因为一对多关系中,多的一方(TvShow)需要持有外键:
@Entity @Table(name = "tvshows") public class TvShow { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id", updatable = false, nullable = false) private int tvShowId; @ManyToOne @JoinColumn(name = "user_id") // Hibernate会在tvshows表生成这个外键字段,关联users表的user_id private User user; @OneToMany(mappedBy = "tvShow", fetch = FetchType.EAGER) // 原代码此处也有误,应指向Season中关联TvShow的属性名 private List<Season> seasons; // 添加必要的getter和setter }
顺带提一句:你原TvShow中关联Season的@OneToMany的mappedBy也写错了,应该指向Season实体里关联TvShow的属性名(比如tvShow),不是seasonId,这里也一起修正了。
2. 修正查询方法
现在关联关系正确了,你有两种方式实现需求:
方式一:直接从User实体获取收藏列表
如果你的UserRepository有根据userId查询用户的方法,直接调用用户的getFavourites()即可:
// 在UserRepository中定义方法 public Optional<User> findByUserId(int userId); // 业务逻辑中使用 Optional<User> userOpt = userRepository.findByUserId(userId); if(userOpt.isPresent()){ List<TvShow> favourites = userOpt.get().getFavourites(); // 返回favourites列表 }
方式二:编写正确的JPQL查询
如果你想直接通过JPQL查询获取收藏列表,需要从User关联到TvShow,而不是直接匹配TvShow的id:
@Query("SELECT t FROM User u JOIN u.favourites t WHERE u.userId = :userId") public List<TvShow> getFavourites(@Param("userId") int userId);
这个查询的逻辑是:找到userId匹配的用户,再关联查询他的收藏TvShow列表。
为什么你的原查询不对?
你原查询SELECT t FROM TvShow t WHERE t.id = :userId是把TvShow的id和用户的userId做匹配,这完全是逻辑错误——你要找的是用户关联的TvShow,不是id恰好等于userId的TvShow。
内容的提问来源于stack exchange,提问作者George Cimpoies
相关产品推荐
相关产品推荐

