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

如何仅用MyBatis注解实现嵌套结果解决N+1查询问题

解决方案:使用MyBatis注解实现嵌套结果映射(避免N+1查询)

1. 修正实体类定义

首先修正Question类中错误的构造函数,给集合字段添加默认值以简化映射:

data class Question(
    val id: Long,
    val title: String,
    val content: String,
    val skillNames: Set<String> = emptySet() // 添加默认值,无需额外构造函数
)

2. 重构QuestionMapper(移除SkillMapper)

通过单表关联查询+嵌套结果映射实现一次SQL获取所有数据,避免N+1问题:

@Mapper
interface QuestionMapper {
    @Select("""
        SELECT
            q.id AS question_id,
            q.title,
            q.content,
            s.name AS skill_name
        FROM
            question q
        LEFT JOIN skill s ON q.id = s.question_id
    """)
    @Results(
        id = "QuestionWithSkillsResultMap",
        value = [
            // 标记主键字段,MyBatis将通过该字段合并重复的Question记录
            Result(property = "id", column = "question_id", id = true),
            Result(property = "title", column = "title"),
            Result(property = "content", column = "content"),
            // 映射关联的技能名称集合
            Result(
                property = "skillNames",
                javaType = Set::class,
                column = "question_id", // 关联主键,确保同一问题的技能被收集
                many = Many(resultMap = "SkillNameResultMap")
            )
        ]
    )
    fun getQuestions(): List<Question>

    // 定义技能名称的单独映射(仅用于结果映射,无需调用)
    @Suppress("unused")
    @Results(
        id = "SkillNameResultMap",
        value = [Result(property = "", column = "skill_name")]
    )
    fun mapSkillName(): String
}

核心原理说明

  • 关联查询:通过LEFT JOIN一次性查询出所有问题及其关联技能,仅触发1次SQL请求,彻底解决N+1问题。
  • 结果合并:标记question_id为id=true,MyBatis会自动将同一问题的多条关联记录合并为一个Question对象。
  • 集合映射:通过@Many关联SkillNameResultMap,MyBatis会将同一问题的所有skill_name自动收集到skillNames集合中。

额外注意事项

  • 若确认所有问题都有1-5个技能,可将LEFT JOIN改为INNER JOIN以减少返回的空技能记录。
  • 确保MyBatis配置中mapUnderscoreToCamelCase参数为true(可选,若使用下划线命名的字段会自动映射为驼峰属性)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 01:27:03