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

JPA OneToMany关联下对子表排序限制并投影的实现方案

结论

完全可以通过JPQL查询或者JPA方法命名约定实现需求,以下是具体实现方案:


前置修正

你当前定义的ParentRepository存在泛型参数错误:Parent实体的主键类型是Long,因此继承JpaRepository时第二个泛型参数需要改为Long而非UUID。

同时你的MyProjection作为封闭投影,需要明确定义和查询字段匹配的getter方法:

interface MyProjection {
    // 方法名和JPQL查询的字段别名一一对应
    fun getParentId(): Long?
    fun getChildId(): Long?
    fun getVersion(): Int?
    fun getData(): String?
}

方案1:JPQL实现(更推荐,可读性更高)

直接在ParentRepository中定义查询即可,Spring Data JPA会自动完成投影映射、排序、取第一条的逻辑:

@Repository
interface ParentRepository : JpaRepository<Parent, Long> {
    @Query("""
        select 
            p.id as parentId, 
            c.id as childId, 
            c.version as version, 
            c.data as data 
        from Parent p 
        join p.children c 
        where p.id = :parentId 
        order by c.version desc
    """)
    fun findWithLatestChild(parentId: Long?): MyProjection?
}

如果你的JPA实现不支持自动识别单条返回加限制,可以在select后加top 1适配:
select top 1 p.id as parentId, ...


方案2:JPA方法命名约定实现

如果不想手动写JPQL,也可以通过符合命名规则的方法名实现,更推荐在ChildRepository中定义,逻辑更直观:

@Repository
interface ChildRepository : JpaRepository<Child, Long> {
    // Top 代表仅返回第一条,ByParentId按父ID过滤,OrderByVersionDesc按version降序
    fun findTopByParentIdOrderByVersionDesc(parentId: Long?): MyProjection?
}

如果一定要在ParentRepository中用方法命名实现,写法如下(可读性稍差):

fun findTopByIdOrderByChildrenVersionDesc(id: Long?): MyProjection?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 17:48:07