Spring中REST API的Get方法实现:按姓名或流派查询艺术家
实现按艺术家姓名或流派查询的REST API接口方案
嘿,我来帮你搞定这个查询接口的问题!结合你给出的实体关联配置,这里有两种靠谱的实现方式,都是Spring Data JPA常用的套路:
方式一:用Spring Data JPA的派生查询方法(最简单)
这种方式不用写JPQL,直接靠方法名就能生成查询语句,非常省心。首先你得把Repository的泛型参数补全(JpaRepository需要实体类和ID类型,假设你的ID是Long),然后添加对应的查询方法:
@Repository public interface ArtistRepository extends JpaRepository<Artist, Long> { // 模糊匹配艺术家姓名,或者模糊匹配关联流派的名称 List<Artist> findByNameContainingOrGenresNameContaining(String artistName, String genreName); // 如果需要精确匹配的话,就把Containing去掉 // List<Artist> findByNameOrGenresName(String artistName, String genreName); }
这里要注意:因为你的Artist实体里关联的属性是private Genres genres;,所以派生方法里要用GenresName(驼峰式)来对应流派实体的name字段。
方式二:自定义JPQL查询(更灵活)
如果你需要更复杂的查询逻辑,或者想自己控制SQL生成,就用@Query注解来写JPQL。这里要注意关联查询的写法,因为是ManyToOne关联,直接JOIN实体的关联属性就行:
@Repository public interface ArtistRepository extends JpaRepository<Artist, Long> { @Query("SELECT a FROM Artist a JOIN a.genres g WHERE a.name LIKE %:artistName% OR g.name LIKE %:genreName%") List<Artist> findByArtistNameOrGenreName( @Param("artistName") String artistName, @Param("genreName") String genreName ); // 解决懒加载问题:如果返回Artist时需要同时加载关联的Genre,用FETCH JOIN @Query("SELECT a FROM Artist a JOIN FETCH a.genres g WHERE a.name LIKE %:artistName% OR g.name LIKE %:genreName%") List<Artist> findByArtistNameOrGenreNameWithGenreLoaded( @Param("artistName") String artistName, @Param("genreName") String genreName ); }
关键注意点:
- 你的实体类如果是
Artist(不是Artists),JPQL里要对应写Artist,不要写错类名 JOIN a.genres g这里的genres是你Artist实体里定义的关联属性名,一定要和实体类里的字段名一致%:param%是用来做模糊匹配的,如果需要精确匹配,直接写成a.name = :artistName就行- 因为你用了
FetchType.LAZY,如果在Controller里直接返回Artist对象,可能会触发懒加载异常(比如序列化的时候访问genre属性),这时候用JOIN FETCH就能一次性加载关联的Genre数据,避免这个问题。
最后在Controller里封装接口
把Repository的方法用到REST接口里,处理请求参数,比如允许用户只传姓名、只传流派,或者两个都传:
@RestController @RequestMapping("/api/artists") public class ArtistController { private final ArtistRepository artistRepository; // 构造注入(推荐的方式) public ArtistController(ArtistRepository artistRepository) { this.artistRepository = artistRepository; } @GetMapping public ResponseEntity<List<Artist>> searchArtists( @RequestParam(required = false) String name, @RequestParam(required = false) String genre) { List<Artist> artists; if (name != null && genre != null) { // 两个参数都传,按姓名或流派查询 artists = artistRepository.findByNameContainingOrGenresNameContaining(name, genre); } else if (name != null) { // 只传姓名,按姓名查询 artists = artistRepository.findByNameContaining(name); } else if (genre != null) { // 只传流派,按流派查询 artists = artistRepository.findByGenresNameContaining(genre); } else { // 什么参数都没传,返回所有艺术家 artists = artistRepository.findAll(); } return ResponseEntity.ok(artists); } }
小建议:
如果你的流派实体类叫Genre(单数)会更符合Java命名规范,对应的Artist里的关联属性改成private Genre genre;,这样派生方法名也会更直观,比如findByNameContainingOrGenreNameContaining。
内容的提问来源于stack exchange,提问作者Jeta Kasabaqi
相关产品推荐
相关产品推荐

