一对一查询 association
通过在resultMap里面配置association节点配置一对一的类就可以完成;
<resultMap type="com.lcb.user.Classes" id="ClassesResultMap">
<!--实体类的字段名和数据表的字段名映射-->
<id property="id"column="c_id"/>
<result property="name"column="c_name"/>
<association property="teacher" javaType="com.lcb.user.Teacher">
<id property="id" column="t_id"/>
<result property="name"column="t_name"/>
</association>
</resultMap>
一对多查询示例 collection
collection节点配置一对多的类就可以完成
MyBatis在映射文件中加载关联关系对象主要通过两种方式:嵌套查询和嵌套结果。 嵌套查询 是指通过执行另外一条SQL映射语句来返回预期的复杂类型;
嵌套结果 是使用嵌套结果映射来处理重复的联合结果的子集。开发人员可以使用上述任意一种方式实现
结构
//问题 实体类
public class Question {
private String id; //ID
private String content; //问题
private String type; //问题类型 1:单选,2:多选,3:问答
private Integer sort; //排序
private List<QuestionOption> options; //问题选项 *** 问题表里不需要有这个属性对应的字段
//...
}
//问题选项 实体类
public class QuestionOption{
private String id; //ID
private String qid; //问题ID *** 问题选项表里需要有这个属性对应的字段
private String content; //选项
private Integer sort; //排序
//...
}
方式一 嵌套查询
代码复用性高, 主表分页查询正确
影响到性能 嵌入sql 每一条记录进行关联查询 加上自身返回结果集查询1次,共需要访问数据库N+1次。
select=”com.xxx.modules.xxx.mapper.QuestionOptionMapper.selectList”
column=”{qid=id,sort=sort}” />
方式二 嵌套结果查询
只需要执行一次sql查询, 主表分页查询不正确
注意: 主子表要查询出来的字段名重复,要起别名
只需要查询一次(复杂的sql), 在内存中组装构造,
延时加载
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载,
association指的就是一对一,collection指的就是一对多查询。
在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()
方法的调用。这就是延迟加载的基本原理。
当然了,不光是Mybatis,几乎所有的包括Hibernate,支持延迟加载的原理都是一样的。
参考文章: