Spring Data JPA嵌套实体属性排序:方法应归属哪个仓库?
问题描述
我需要根据给定的Car VIN集合获取排序后的Model列表,编写了如下查询方法:
@Query("select distinct c.model" + "from Car c " + "where c.id in :vins") public Set<Model> findDistinctModelForCarIdsIn(@Param("vins") Set<Integer> vins, Sort sort);
但将该方法放在ModelRepository中时,排序不生效:
http://localhost/api/models/search/findDistinctModelForCarIdsIn?vins=16203,25617,42661&sort=model.name,asc
而将其放在CarRepository中时,排序正常生效:
http://localhost/api/cars/search/findDistinctModelForCarIdsIn?vins=16203,25617,42661&sort=model.name,asc
我的领域对象定义如下:
class Car { Integer id; @ManyToOne Model model; } class Model { Integer id; String name; }
请问这是为什么?是否规则是将方法放在查询源实体(如Car)对应的仓库,而非查询结果实体(如Model)的仓库?
原因分析
仓库实体上下文的匹配问题
ModelRepository的根实体是Model,当你传入sort=model.name,asc时,Spring Data JPA会尝试从Model实体中解析model.name这个路径,但Model本身并没有名为model的属性,自然无法识别这个排序条件,导致排序失效。
而CarRepository的根实体是Car,model.name是合法的关联路径(Car关联到Model,再取name属性),Spring Data能正确解析并生成对应的ORDER BY model.name ASC语句,所以排序生效。自定义查询的排序绑定逻辑
自定义查询的排序参数解析依赖于当前仓库对应的根实体:- 若在
ModelRepository中使用该查询,即使把排序参数改成sort=name,asc,由于查询本身是从Car表关联查询Model,Spring Data在绑定排序条件时,可能无法正确将排序应用到查询结果上(因为上下文是Model,但查询的数据源是Car)。 - 放在
CarRepository中时,根实体与查询数据源一致,排序参数的路径能直接匹配实体关联关系,逻辑完全通顺。
- 若在
结论
是的,这类查询方法确实应该放在查询源实体(Car)对应的仓库中,原因如下:
- 查询的数据源是
Car表,仓库的实体上下文与数据源匹配时,Spring Data才能正确解析关联路径的排序参数。 - 若硬要在
ModelRepository中实现,需要调整排序参数为name,asc,同时在JPQL查询中显式添加ORDER BY c.model.name,但这种方式不仅不直观,还容易因上下文不匹配出现其他问题。
内容的提问来源于stack exchange,提问作者James
相关产品推荐
相关产品推荐

