MyBatis之级联小结

在这之前我们知道了MyBatis为我们提供了三种级联:一对一关系(assocation)、一对多关系(collection)、鉴别器(discriminator)。在最后一个鉴别器例子中,看到了当层级关系比较负责时,我们似乎已经难以应对和维护各种级联关系,在对数据库进行查询是否应用MyBatis为我们提供的级联这需要在实际中去斟酌和取舍。在我们通过级联来查询信息时会发现有一个问题,当我们只想查询出学生的普通信息(姓名、性别),而不想查询出他的成绩、课程、体检表时,之前的三个例子不管你是否需要成绩、课程等信息它都会去执行,只要有一个关联。这并不是我们所想要的,我们所想要的是,我需要时才去执行这条sql,我需要成绩时才将此条sql发送到数据库查询出结果,不需要时就不需要发送到数据库进行查询。很高兴的是,MyBatis为我们提供了这一需求,即:lazyLoadingEnabled。

我们在mybatis-config.xml配置文件中做一下配置:

<settings>
    <setting name="lazyLoadingEnabled" value="true"/><!-- 开启懒加载模式(按需加载),默认情况下是即时加载 -->
</settings>

这句话的意思就是我们上面所要想达到的效果——按需加载。但其实只有这么一句话是不够的,MyBatis的延迟加载方式是按层级延迟加载。

当我们在查询学生的基本信息时,MyBatis会根据鉴别器去找到健康情况。而在当我们访问课程成绩时,由于学生证和课程成绩出于同一层级,所以学生证也会跟着被加载。只有课程不是和课程成绩出于同一层级,所以它不会被加载。这还没有达到我们想要的“按需加载”效果,我们所想要达到的按需加载是真正只有用到的时候才会去加载。这个时候就需要在刚刚的配置文件中再做以下的配置:

<settings>
    <setting name="lazyLoadingEnabled" value="true"/><!-- 开启懒加载模式(按需加载),默认情况下是即时加载 -->
    <setting name="aggressiveLazyLoading" value="false"/>
</
settings>

attressiveLazyLoading配置项,意思就是这个意思——侵略性延迟加载。

这实际上是在mybatis-config.xml文件中做的全局配置,当想要针对某些属性进行延迟加载,对某些属性进行立即加载时,我们可以细化到具体的mapper映射配置文件中去。例如StudentMapper.xml:

 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE mapper  
 3   PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"  
 4   "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 5 <mapper namespace="day_8_mybatis.mapper.StudentMapper">
 6     <resultMap type="day_8_mybatis.pojo.Student" id="studentMap">
 7         <id property="id" column="id"/>
 8         <result property="name" column="name"/>
 9         <result property="sex" column="sex"/>
10         <association property="selfCard" column="id" select="day_8_mybatis.mapper.SelfCardMapper.findSelfCardByStudentId" fetchType="lazy"/>
11         <collection property="courseScoreList" column="id" select="day_8_mybatis.mapper.CourseScoreMapper.findCourseScoreByStudentId" fetchType="eager"/>
12         <discriminator javaType="string" column="sex">
13             <case value="男" resultMap="maleStudentMap"/>
14             <case value="女" resultMap="femaleStudentMap"/>
15         </discriminator>
16     </resultMap>
17 <!--以下省略-->

在第10行中我们对查询出学生的学生证信息配置为延迟加载,第11行中我们对查询出学生的课程成绩做了立即加载配置。

以上几乎就是MyBatis级联的全部内容,至于用级联还是用sql的join语句只有在实际中去认真仔细考量和权衡。

<think>好的,我现在需要帮助用户解决MyBatis级联映射的配置方法及常见问题排查。首先,我得回忆一下MyBatis的相关知识,特别是级联映射的部分。用户可能对MyBatis的association和collection不太熟悉,需要详细说明配置步骤。 首先,级联映射主要有一对一、一对多和多对多的情况。每种情况对应的XML配置方式不同。比如一对一用association,一对多用collection。然后,分步查询和联表查询的区别也很重要,用户可能需要了解这两种方法的优缺点,比如性能方面分步查询可能更好,但需要多次查询数据库。 接下来,我需要检查常见的配置错误。例如,属性名和列名是否对应,是否忽略了jdbcType,以及是否配置了正确的resultMap嵌套。还有,延迟加载的问题,如果分步查询时没有开启延迟加载,可能会导致N+1查询问题,影响性能。 然后,根据用户提供的引用内容,引用[2]中提到了级联查询的几种方式,包括association和分步查询,还有一对多的处理。引用[4]提到联表查询可以先在命令行调试SQL,这可能帮助用户检查SQL是否正确。需要建议用户先在数据库工具里验证联表查询的SQL语句是否正确,再放到MyBatis的映射文件中。 另外,用户提供的引用[1]是关于枚举处理的,可能和当前问题关系不大,但引用[3]提到Spring Boot的事务管理,虽然不直接相关,但如果在级联查询中有事务问题,可能需要考虑,不过当前问题主要还是配置层面。 用户可能遇到的常见问题包括结果映射不正确,比如属性未正确映射,或者分步查询的select语句未正确指向。这时候需要检查column属性传递的外键是否正确,以及select中的命名空间和方法名是否正确。 延迟加载的配置也需要检查是否在mybatis-config.xml中启用了,或者是否在application.properties中配置了相应的设置(如果是Spring Boot项目)。例如,需要设置lazyLoadingEnabled为true。 还有,多对多的关系通常需要通过中间表处理,需要使用collection来映射多个关联对象,并且可能需要结合两个一对多的配置。 最后,生成相关问题的时候,需要考虑用户可能进一步的问题,比如性能优化、延迟加载配置、多对多处理的具体例子,以及如何排查结果不匹配的问题。需要确保这些问题与当前主题紧密相关,帮助用户深入理解级联映射的各个方面。</think>### MyBatis 级联映射配置方法及常见问题排查 #### 一、级联映射配置方法 1. **一对一关系(association)** - **联表查询**:通过单条 SQL 实现关联查询,需在 `resultMap` 中嵌套 `association`。 ```xml <resultMap id="studentWithClass" type="Student"> <id property="id" column="id"/> <result property="name" column="name"/> <association property="class" javaType="Class"> <id property="classId" column="class_id"/> <result property="className" column="class_name"/> </association> </resultMap> ``` SQL 需包含学生表和班级表的联查字段[^4]。 - **分步查询**:通过多次查询实现,需配置 `select` 属性指向另一查询。 ```xml <association property="class" select="com.dao.ClassMapper.selectById" column="class_id"/> ``` 2. **一对多关系(collection)** - **联表查询**:使用 `collection` 标签映射集合属性。 ```xml <resultMap id="classWithStudents" type="Class"> <collection property="students" ofType="Student"> <id property="id" column="student_id"/> <result property="name" column="student_name"/> </collection> </resultMap> ``` - **分步查询**:通过 `select` 方法实现按需加载。 ```xml <collection property="students" select="com.dao.StudentMapper.selectByClassId" column="class_id"/> ``` 3. **多对多关系** - 需通过中间表实现,结合两个 `collection` 分别映射关联对象集合。 ```xml <resultMap id="studentWithCourses" type="Student"> <collection property="courses" ofType="Course" columnPrefix="course_"> <id property="id" column="id"/> <result property="name" column="name"/> </collection> </resultMap> ``` --- #### 二、常见问题排查 1. **映射字段缺失或错误** - **现象**:部分属性值为 `null`。 - **排查**:检查 `resultMap` 中字段名与数据库列名是否一致,联表查询时是否包含所有需要的字段[^4]。 2. **分步查询未生效** - **现象**:关联对象未加载。 - **排查**: - 确认 `select` 指向的 SQL 方法路径正确[^2]。 - 检查 `column` 传递的外键值是否有效。 3. **N+1 查询问题** - **现象**:执行大量冗余 SQL。 - **解决**:启用延迟加载(需在配置文件中设置 `lazyLoadingEnabled=true`)。 4. **类型不匹配** - **现象**:抛出 `TypeException`。 - **排查**:检查 `javaType` 或 `ofType` 是否正确定义,例如集合属性需指定 `ofType`。 5. **循环依赖问题** - **现象**:序列化时栈溢出。 - **解决**:使用 `@JsonIgnore` 注解或在 DTO 中裁剪关联字段。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值