一对一查询 association

通过在resultMap里面配置association节点配置一对一的类就可以完成;

  1. <resultMap type="com.lcb.user.Classes" id="ClassesResultMap">
  2. <!--实体类的字段名和数据表的字段名映射-->
  3. <id property="id"column="c_id"/>
  4. <result property="name"column="c_name"/>
  5. <association property="teacher" javaType="com.lcb.user.Teacher">
  6. <id property="id" column="t_id"/>
  7. <result property="name"column="t_name"/>
  8. </association>
  9. </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次。






ofType=”com.xxx.modules.xxx.entity.QuestionOption”
select=”com.xxx.modules.xxx.mapper.QuestionOptionMapper.selectList”
column=”{qid=id,sort=sort}” />





方式二 嵌套结果查询

只需要执行一次sql查询, 主表分页查询不正确
注意: 主子表要查询出来的字段名重复,要起别名

只需要查询一次(复杂的sql), 在内存中组装构造,







ofType=”com.xxx.modules.data.entity.QuestionOption”>







延时加载

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,支持延迟加载的原理都是一样的。


参考文章:

  1. https://blog.csdn.net/Jiangbohao_/article/details/106626109