JPA CriteriaQuery实现ManyToMany关联下查询同关联艺人的歌曲
完整实现代码
Song song = null; // 已获取到目标歌曲实例 Collection<Artist> artists = song.getArtists(); CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery<Song> criteria = builder.createQuery(Song.class); Root<Song> root = criteria.from(Song.class); // 构造子查询,查询所有关联了目标艺人的歌曲ID Subquery<Long> subquery = criteria.subquery(Long.class); Root<Song> subRoot = subquery.from(Song.class); // 关联Song和Artist的多对多关系,Hibernate会自动映射到song_artists中间表 Join<Song, Artist> artistJoin = subRoot.join("artists"); // 子查询筛选条件:关联的艺人属于目标艺人集合 subquery.select(subRoot.get("id")) .where(artistJoin.in(artists)); // 主查询条件:歌曲ID在子查询结果中,若需排除原歌曲可追加 notEqual 条件 criteria.select(root) .where( root.get("id").in(subquery) // 可选:排除原始查询的歌曲本身 // , builder.notEqual(root.get("id"), song.getId()) ); // 执行查询得到结果 List<Song> relatedSongs = entityManager.createQuery(criteria).getResultList();
关键说明
- 不需要手动操作中间表,直接通过实体的
artists关联属性做join,Hibernate会自动生成符合@JoinTable配置的SQL语句 artistJoin.in(artists)底层会自动用Artist的主键字段做匹配,不需要手动提取艺人ID拼接- 最终生成的SQL逻辑和你给出的原生参考SQL完全一致,性能无额外损耗
内容的提问来源于stack exchange,提问作者Sally Mwalr
相关产品推荐
相关产品推荐

