Mybatis面试总结(中):MyBatis是否支持延迟加载,其原理是什么?不同xml映射文件,id是否可重复?有哪些Executor执行器?是否可映射 Enum 枚举类?TypeHandler作用?

仅供自学使用,大部分内容来自javaGuide,请支持原版书籍。

MyBatis 是否支持延迟加载?如果支持,它的实现原理是什么?

MyBatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association 指的就是一对一,collection 指的就是一对多查询。
MyBatis 配置文件中,可以配置是否启用延迟加载:lazyLoadingEnabled=true | false


其实现原理如下:

  • 定义关联关系:
    在 MyBatis 的映射文件中,我们定义了对象之间的关联关系,比如一个 User 对象关联一个 Address 对象。
  • 创建代理对象:
    当 MyBatis 查询 User 对象时,它不会立即查询关联的 Address 对象。而是为 Address 对象创建一个 CGLIB 代理对象,并将这个代理对象设置到 User 的 address 属性中。
  • 拦截方法调用:
    这个代理对象重写了 Address 类的所有方法。当调用 User 对象的 getAddress() 方法时,实际上获得的是 Address 的代理对象。
  • 触发延迟加载:
    当通过代理对象调用 Address 的方法(如 getName())时,CGLIB 代理会拦截这个调用,并执行 InvocationHandler 的 invoke 方法。
  • 执行查询:
    在 invoke 方法中,代理逻辑会检查真实的数据是否已经被加载。如果尚未加载(即属性值为 null),则会执行预先定义好的 SQL 语句去数据库中查询 Address 对象的数据。
  • 设置真实对象:
    查询完成后,代理逻辑会将查询到的 Address 对象设置到 User 的 address 属性中,替换原来的代理对象。
  • 完成方法调用:
    最后,代理逻辑会调用真实 Address 对象的相应方法(如 getName()),并返回结果。

示例流程
以 a.getB().getName() 为例:

  • 初始状态:
    a 是一个 User 对象,b 是一个 Address 的代理对象,实际的数据尚未加载。
  • 调用 a.getB():
    返回 Address 的代理对象。
  • 调用 getName():
    代理对象拦截调用,进入 invoke 方法。
  • 检查并加载数据:
    invoke 方法发现 b 的真实数据为 null,执行 SQL 查询加载 Address 数据。
  • 设置真实对象:
    将查询到的 Address 对象设置到 a 的 b 属性中。
  • 调用真实方法:
    调用真实 Address 对象的 getName() 方法,返回结果。

通过这种方式,MyBatis 实现了延迟加载,只有在真正需要使用关联对象的数据时才去查询数据库,从而提高了性能。

需要注意的是,由于使用了代理对象,在进行序列化或反射操作时需要特别注意。

MyBatis 的 xml 映射文件中,不同的 xml 映射文件,id 是否可以重复?

不同的 xml 映射文件,如果配置了 namespace,那么 id 可以重复;如果没有配置 namespace,那么 id 不能重复;

原因就是 namespace+id 是作为 Map 的 key 使用的。

MyBatis 都有哪些 Executor 执行器?它们之间的区别是什么?

MyBatis 有三种基本的 Executor 执行器:

  • SimpleExecutor: 每执行一次 update 或 select,就开启一个 Statement 对象,用完立刻关闭 Statement 对象。
  • ReuseExecutor: 执行 update 或 select,以 sql 作为 key 查找 Statement 对象,存在就使用,不存在就创建,用完后,不关闭 Statement 对象,而是放置于 Map内,供下一次使用。简言之,就是重复使用 Statement 对象。
  • BatchExecutor:执行 update(没有 select,JDBC 批处理不支持 select),将所有 sql 都添加到批处理中(addBatch()),等待统一执行(executeBatch()),它缓存了多个 Statement 对象,每个 Statement 对象都是 addBatch()完毕后,等待逐一执行 executeBatch()批处理。与 JDBC 批处理相同。

作用范围:Executor 的这些特点,都严格限制在 SqlSession 生命周期范围内。

在 MyBatis 配置文件中,可以指定默认的 ExecutorType 执行器类型,也可以手动给 DefaultSqlSessionFactory 的创建 SqlSession 的方法传递 ExecutorType 类型参数。

MyBatis 是否可以映射 Enum 枚举类?TypeHandler作用是什么?

MyBatis 可以映射枚举类,不单可以映射枚举类,MyBatis 可以映射任何对象到表的一列上。映射方式为自定义一个 TypeHandler ,实现 TypeHandler 的 setParameter() 和 getResult() 接口方法。


TypeHandler 有两个作用:一是完成从 javaType 至 jdbcType 的转换;二是完成 jdbcType 至 javaType 的转换,体现为 setParameter() 和 getResult() 两个方法,分别代表设置 sql 问号占位符参数和获取列查询结果。

你可能感兴趣的:(Mybatis面试总结,mybatis,面试,xml,java,延迟加载)