在关系型数据库中,我们经常要处理一对一 、 一对多的关系 。 例如, 一辆汽车需要有一个引擎,这是一对一的
关系。 一辆汽车有 4 个或更多个轮子,这是一对多的关系 。关联元素就是专门用来处理关联关系的。
在java类中关联关系也有三种,一对一,一对多,多对多
一对一 在本类中定义对方类型的对象,如A类中定义B类类型的属性b,B类中定义A类类型的属性a
一对多 一个A类类型对应多个B类类型的情况,需要在A类中以集合的方式引入B类类型的对象,在B类中定义A类类型的属性a
多对多 在A类中定义B类类型的集合,在B类中定义A类类型的集合
一 、两种关联方式
嵌套结果:使用嵌套结果映射来处理重复的联合结果的子集
嵌套查询:通过执行另外一个 SQL 映射语句来返回预期的复杂类型
对于嵌套查询可以使用懒加载方法实现优化
*Mybatis的延迟加载配置
在全局配置文件中加入下面代码
<settings>
<setting name="lazyLoadingEnabled" value="true" />
<setting name="aggressiveLazyLoading" value="false"/>
</settings>
在映射文件中,<association>元素和<collection>元素中都已默认配置了延迟加载属性,即默认属性fetchType="lazy"(属性fetchType="eager"表示立即加载),所以在配置文件中开启延迟加载后,无需在映射文件中再做配置
二 、具体分析
2.1 一对一关系查询 <association>标签
使用<association>元素进行一对一关联映射非常简单,只需要参考如下两种示例配置即可

下面使用一个例子来验证。有两个对象,一个为员工、一个为职位。员工对象中包含职位 为一对一关系。
public class TUser {
private Integer id;
private String userName;
private String realName;
private Byte sex;
private String mobile;
private String email;
private String note;
private Integer positionId;
//职位
private TPosition position;
}
public class TPosition {
private Integer id;
//职位
private String postName;
private String note;
}
嵌套结果
<resultMap id="BaseResultMap" type="com.study.mybatis.entity.TUser">
<id column="id" property="id" jdbcType="INTEGER" />
<result column="user_name" property="userName" jdbcType="VARCHAR" />
<result column="real_name" property="realName" jdbcType="VARCHAR" />
<result column="sex" property="sex" jdbcType="TINYINT" />
<result column="mobile" property="mobile" jdbcType="VARCHAR" />
<result column="email" property="email" jdbcType="VARCHAR" />
<result column="note" property="note" jdbcType="VARCHAR" />
<result column="position_id" property="positionId" jdbcType="INTEGER" />
</resultMap>
<resultMap id="userAndPosition1" extends="BaseResultMap" type="com.study.mybatis.entity.TUser">
<association property="position" javaType="TPosition" >
<id column="post_id" property="id"/>
<result column="post_id" property="postName"/>
<result column="post_note" property="note"/>
</association>
</resultMap>
<select id="selectUserPosition1" resultMap="userAndPosition1">
select a.id,user_name,real_name,sex,mobile,email,a.note,a.position_id ,b.id post_id,b.post_name,b.note post_note
from t_user a,t_position b where a.position_id = b.id
</select>

嵌套查询
<resultMap id="userAndPosition2" extends="BaseResultMap" type="com.study.mybatis.entity.TUser">
<association property="position" column="position_id" fetchType="lazy"
select="com.study.mybatis.mapper.TPositionMapper.selectByPrimaryKey">
</association>
</resultMap>
<select id="selectUserPosition2" resultMap="userAndPosition2">
select a.id,a.user_name,a.real_name,a.sex,a.mobile,a.position_id from t_user a
</select>

2.2 collection 一对多关系
<resultMap>元素中,包含了一个<collection>子元素,MyBatis就是通过该元素来处理一对多关联关系的
<collection>子元素的属性大部分与<association>元素相同,但其还包含一个特殊属性--ofType
ofType属性与javaType属性对应,它用于指定实体对象中集合类属性所包含的元素类型。
<collection >元素的使用也非常简单,同样可以参考如下两种示例进行配置,具体代码如下: 
嵌套结果
<resultMap id="userAndJobs1" extends="BaseResultMap" type="TUser">
<collection property="jobs"
ofType="com.enjoylearning.mybatis.entity.TJobHistory" >
<result column="comp_name" property="compName" jdbcType="VARCHAR" />
<result column="years" property="years" jdbcType="INTEGER" />
<result column="title" property="title" jdbcType="VARCHAR" />
</collection>
</resultMap>
<select id="selectUserJobs1" resultMap="userAndJobs1">
select a.id,a.user_name,a.real_name,a.sex,a.mobile,b.comp_name,b.years,b.title
from t_user a,t_job_history b where a.id = b.user_id
</select>
嵌套查询
<resultMap id="userAndJobs2" extends="BaseResultMap" type="TUser">
<collection property="jobs" fetchType="lazy" column="id"
select="com.study.mybatis.mapper.TJobHistoryMapper.selectByUserId" />
</resultMap>
<select id="selectUserJobs2" resultMap="userAndJobs2">
select a.id,a.user_name,a.real_name,a.sex, a.mobilefrom t_user a
</select>

2.3 多对多
多对多的关联关系查询,同样可以使用前面介绍的<collection >元素进行处理(其用法和一对多关联关系查询语句用法基本相同)
<resultMap type="TUser" id="userRoleInfo" extends="BaseResultMap">
<collection property="roles" ofType="TRole" columnPrefix="role_">
<result column="id" property="id" />
<result column="Name" property="roleName" />
<result column="note" property="note" />
</collection>
</resultMap>
<select id="selectUserRole" resultMap="userRoleInfo">
select a.id,a.user_name,a.real_name,a.sex,a.mobile,a.note,b.role_id,c.role_name,c.note role_note
from t_user a, t_user_role b,t_role c where a.id = b.user_id AND b.role_id = c.id
</select>
2.4 discriminator 鉴别器映射
在特定的情况下使用不同的pojo进行关联, 鉴别器元素就是被设计来处理这个情况的。鉴别器非常容易理解,因为它
的表现很像 Java 语言中的 switch 语句;
- discriminator 标签常用的两个属性如下:
- column:该属性用于设置要进行鉴别比较值的列 。
- javaType:该属性用于指定列的类型,保证使用相同的 Java 类型来比较值。
- discriminator 标签可以有1个或多个 case 标签, case 标签包含以下三个属性 。
- value : 该值为 discriminator 指定 column 用来匹配的值 。
- resultMap : 当column的值和value的值匹配时,可以配置使用resultMap指定的映射,resultMap优先级高于 resultType
- resultType : 当 column 的值和 value 的值匹配时,用于配置使用 resultType指定的映射。
<resultMap id="userAndHealthReportMale" extends="userAndHealthReport" type="TUser">
<collection property="healthReports" column="id"
select= "com.study.mybatis.mapper.THealthReportMaleMapper.selectByUserId"></collection>
</resultMap>
<resultMap id="userAndHealthReportFemale" extends="userAndHealthReport" type="TUser">
<collection property="healthReports" column="id"
select= "com.study.mybatis.mapper.THealthReportFemaleMapper.selectByUserId"></collection>
</resultMap>
<resultMap id="userAndHealthReport" extends="BaseResultMap" type="TUser">
<discriminator column="sex" javaType="int">
<case value="1" resultMap="userAndHealthReportMale"/>
<case value="2" resultMap="userAndHealthReportFemale"/>
</discriminator>
</resultMap>
<select id="selectUserHealthReport" resultMap="userAndHealthReport">
select
<include refid="Base_Column_List" />
from t_user a
</select>
本文详细介绍了Mybatis中处理关联关系的三种方式:一对一、一对多和多对多。通过<association>、<collection>和discriminator标签的应用,展示了如何在映射文件中配置这些关联查询,包括嵌套结果和嵌套查询的实现。同时,文中提到了延迟加载的配置和使用,帮助理解Mybatis在处理复杂对象关系时的策略。
1107





