如何通过@Query注解获取包含所有关联学校的指定城市?
获取包含关联学校的指定城市的几种方法
嘿,这个问题我之前也碰到过!因为JPA默认对@OneToMany关联用的是懒加载(FetchType.LAZY),直接查City的话,schools集合是个代理对象,在Controller里访问很容易触发懒加载异常。下面给你两种靠谱的解决方案,都可以用在你的CityRepository里,然后在Controller里调用就行:
方法一:用@Query写Fetch Join的JPQL
这种方式最直接,通过JPQL的JOIN FETCH一次性把City和它的schools都查出来,避免N+1查询问题:
@Repository public interface CityRepository extends JpaRepository<City, Long>{ @Query("SELECT c FROM City c JOIN FETCH c.schools WHERE c.id = :cityId") Optional<City> findByIdWithSchools(@Param("cityId") Long cityId); }
然后在你的CityController里调用这个方法:
@GetMapping("/{id}") public ResponseEntity<City> getCityWithSchools(@PathVariable Long id) { return cityRepository.findByIdWithSchools(id) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); }
方法二:用@EntityGraph简化代码
如果你不想写JPQL,Spring Data JPA的@EntityGraph注解可以帮你更简洁地实现同样的效果,它会告诉JPA在查询City时同时抓取关联的schools属性:
@Repository public interface CityRepository extends JpaRepository<City, Long>{ @EntityGraph(attributePaths = {"schools"}) Optional<City> findById(Long cityId); }
这种情况下Controller里直接调用默认的findById方法就行,因为注解已经帮我们处理了关联抓取:
@GetMapping("/{id}") public ResponseEntity<City> getCityWithSchools(@PathVariable Long id) { return cityRepository.findById(id) .map(ResponseEntity::ok) .orElse(ResponseEntity.notFound().build()); }
小提醒
- 两种方法本质都是解决懒加载的问题,一次性加载关联数据,避免在事务外访问懒加载集合导致的异常。
- 如果是查询多个City并关联schools,用Fetch Join要注意分页的问题(可能需要额外处理),但你这里是查单个城市,完全没问题。
内容的提问来源于stack exchange,提问作者James Hao
相关产品推荐
相关产品推荐

