You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JPA如何根据演员ID查询关联电视剧及分集列表

问题背景
  • 需求:根据演员ID(Actor Id)查询对应的电视剧(tv_shows)列表
  • 现状:已实现根据演员ID查询对应分集(chapters)列表的功能,用相同逻辑直接查询TvShow实体时触发报错
  • 约束:不希望额外新建数据表,不确定是否必须建表才能实现Actor到TvShow的关联访问
  • 库表关系:层级为 tv_shows > seasons > chapters,独立actors表,通过chapters_has_actors多对多中间表关联章节和演员,数据库EER图:查看数据库EER图

现有实体定义

TvShow.java

@Entity
@Table(name = "TV_SHOWS")
public class TvShow implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "NAME")
    private String name;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "tvShow")
    private List<Season> seasons;

// Getters and Setters
}

Season.java

@Entity
@Table(name = "SEASONS")
public class Season implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "NAME")
    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "TV_SHOW_ID", nullable = false)
    private TvShow tvShow;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "season")
    private List<Chapter> chapters;

// Getters and Setters
}

Chapter.java

@Entity
@Table(name = "CHAPTERS")
public class Chapter implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "SEASON_ID", nullable = false)
    private Season season;
    
    @ManyToMany(fetch = FetchType.LAZY)
    @JoinTable (name = "CHAPTERS_HAS_ACTORS",
            joinColumns = @JoinColumn(name = "CHAPTER_ID"),
            inverseJoinColumns = @JoinColumn(name ="ACTOR_ID"))
    private List<Actor> actor;

// Getters and Setters
}

已实现的分集查询代码

ChapterServiceImpl.java

@Service
public class ChapterServiceImpl implements ChapterService {

    @Autowired
    private ChapterRepository chapterRepository;
    @Autowired
    private ActorRepository actorRepository;

    private ModelMapper modelMapper = new ModelMapper();

    @Override
    public List<ChapterRest> getChaptersByActorId(Long actorId){
        Optional<Actor> actor = actorRepository.findById(actorId);
        List<ChapterRest> chapterList =  chapterRepository.findByActorId(actorId)
                .stream()
                .map(chapter -> modelMapper
                .map(chapter, ChapterRest.class))
                .collect(Collectors.toList());
        return chapterList;
    }

ChapterControllerImpl.java

@RestController
@RequestMapping("/tv-shows/{tvShowId}/seasons/{seasonNumber}/chapters")
public class ChapterControllerImpl implements ChapterController {

    @Autowired
    private ChapterService chapterService;

    @Override
    @GetMapping(value = "/actors", produces = MediaType.APPLICATION_JSON_VALUE)
    public List<ChapterRest> getChaptersByActorId(
            @RequestParam Long actorId) {
        return chapterService.getChaptersByActorId(actorId);
    }
}

ChapterRepository.java

@Repository
public interface ChapterRepository extends JpaRepository<Chapter, Long> {
    List<Chapter> findByActorId(Long actorId);
}

实现方案

不需要新建任何数据表,现有表关联关系已完全支持跨层级查询,通过JPA嵌套属性路径派生查询即可实现,具体操作如下:

  • 新建TvShow对应的Repository接口,利用JPA支持的嵌套关联属性路径派生查询方法,框架会自动生成跨表关联的SQL语句:
@Repository
public interface TvShowRepository extends JpaRepository<TvShow, Long> {
    // 关联路径:TvShow.seasons -> Season.chapters -> Chapter.actor -> Actor.id
    // 加Distinct关键字避免同一部剧因演员参演多集返回重复记录
    List<TvShow> findDistinctBySeasonsChaptersActorId(Long actorId);
}
  • 优化查询性能,在Repository方法上添加@EntityGraph注解指定需要一次性加载的关联属性,避免懒加载导致的JSON序列化异常,同时解决多层关联带来的N+1查询问题:
@Repository
public interface TvShowRepository extends JpaRepository<TvShow, Long> {
    @EntityGraph(attributePaths = {"seasons", "seasons.chapters", "seasons.chapters.actor"})
    List<TvShow> findDistinctBySeasonsChaptersActorId(Long actorId);
}
  • 补充对应的Service、Controller层逻辑,调用上述Repository方法即可返回带关联季、分集数据的电视剧列表,全程不需要修改现有数据库结构。

注意:如果不需要返回全量的季、分集关联数据,可以根据业务需求调整@EntityGraph中attributePaths的加载范围,减少不必要的数据查询。


内容的提问来源于stack exchange,提问作者Stage

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 13:39:18