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

使用Kotlin JOOQ与MySQL实现两层嵌套集合查询映射报错求助

两层嵌套集合JOOQ查询映射Kotlin数据类失败问题解决

我在构建两层嵌套集合的JOOQ查询时遇到类型转换错误,无法将查询结果映射到Kotlin数据类。期望得到的数据结构如下:

[
    {
        "name": "My Super Region",
        "regions": [
            {
                "name": "My Region",
                "locations": [
                    {
                        "name": "My Location"
                    }
                ]
            }
        ]
    }
]

查看JOOQ查询的中间Result数据结构符合预期,但映射时抛出类型转换异常,报错信息如下:

java.lang.ClassCastException: class org.jooq.impl.RecordImpl3 cannot be cast to class com.abcxyz.repository.LocationsRepository$RegionRecord (org.jooq.impl.RecordImpl3 is in unnamed module of loader 'app'; com.abcxyz.LocationsRepository$RegionRecord is in unnamed module of loader io.ktor.server.engine.OverridingClassLoader$ChildURLClassLoader @f68f0dc)

我的实现代码如下:

fun getRegions(): List<SuperRegionRecord> {
    return DSL.using(dataSource, SQLDialect.MYSQL)
        .select(
            SUPER_REGIONS.ID,
            SUPER_REGIONS.NAME,
            multiset(
                select(
                    REGIONS.ID,
                    REGIONS.NAME,
                    multiset(
                        select(
                            LOCATIONS.ID,
                            LOCATIONS.NAME,
                        )
                        .from(LOCATIONS)
                        .where(LOCATIONS.REGION_ID.eq(REGIONS.ID))
                    ).`as`("locations")
                )
                .from(REGIONS)
                .where(REGIONS.SUPER_REGION_ID.eq(SUPER_REGIONS.ID))
            ).`as`("regions"),
        )
        .from(SUPER_REGIONS)
        .fetchInto(SuperRegionRecord::class.java)
}

data class SuperRegionRecord(
    val id: Int?,
    val name: String?,
    val regions: List<RegionRecord>?
)

data class RegionRecord(
    val id: Int?,
    val name: String?,
    val locations: List<LocationRecord>?
)

data class LocationRecord(
    val id: Int?,
    val name: String?
)

问题原因

JOOQ的fetchInto方法无法自动将嵌套的multiset返回的Record对象递归映射到自定义Kotlin数据类,它仅能处理顶层字段的映射,嵌套集合内的Record不会自动转换为RegionRecord或LocationRecord,因此触发类型转换异常。

解决方法

需要手动处理嵌套集合的映射,或借助JOOQ的RecordMapper实现递归转换,以下是两种可行方案:

方案1:使用map方法手动映射

在fetch之后手动将顶层Record转换为目标数据类,同时递归处理嵌套集合:

fun getRegions(): List<SuperRegionRecord> {
    return DSL.using(dataSource, SQLDialect.MYSQL)
        .select(
            SUPER_REGIONS.ID,
            SUPER_REGIONS.NAME,
            multiset(
                select(
                    REGIONS.ID,
                    REGIONS.NAME,
                    multiset(
                        select(LOCATIONS.ID, LOCATIONS.NAME)
                            .from(LOCATIONS)
                            .where(LOCATIONS.REGION_ID.eq(REGIONS.ID))
                    ).`as`("locations")
                )
                .from(REGIONS)
                .where(REGIONS.SUPER_REGION_ID.eq(SUPER_REGIONS.ID))
            ).`as`("regions"),
        )
        .from(SUPER_REGIONS)
        .fetch()
        .map { record ->
            SuperRegionRecord(
                id = record[SUPER_REGIONS.ID],
                name = record[SUPER_REGIONS.NAME],
                regions = record["regions", Result::class.java]?.map { regionRecord ->
                    RegionRecord(
                        id = regionRecord[REGIONS.ID],
                        name = regionRecord[REGIONS.NAME],
                        locations = regionRecord["locations", Result::class.java]?.map { locationRecord ->
                            LocationRecord(
                                id = locationRecord[LOCATIONS.ID],
                                name = locationRecord[LOCATIONS.NAME]
                            )
                        }
                    )
                }
            )
        }
}

方案2:配置全局RecordMapperProvider(适合项目全局复用)

若希望项目中所有嵌套映射自动处理,可配置JOOQ的RecordMapperProvider,结合Kotlin反射或Jackson实现递归映射,这种方式适合较大规模的项目,需要额外的全局配置。

另外需确保数据类字段名与查询选中的字段名完全匹配(包括大小写,MySQL默认不区分大小写,但代码中需保持一致),避免字段匹配失败导致的映射问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 10:02:28