Mybatis面试题

1.Mybatis 是否支持延迟加载?

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

2.延迟加载的基本原理是什么?

延迟加载的基本原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法。

比如调用a.getB().getName(),拦截器 invoke()方法发现 a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用a.setB(b),于是 a 的对象 b 属性就有值了,接着完成a.getB().getName()方法的调用。

if (lazyLoader.size() > 0 && !FINALIZE_METHOD.equals(methodName)) {
  if (aggressive || lazyLoadTriggerMethods.contains(methodName)) {
    lazyLoader.loadAll();
  } else if (PropertyNamer.isSetter(methodName)) {
    final String property = PropertyNamer.methodToProperty(methodName);
    lazyLoader.remove(property);
  } else if (PropertyNamer.isGetter(methodName)) {
    final String property = PropertyNamer.methodToProperty(methodName);
    if (lazyLoader.hasLoader(property)) {
      lazyLoader.load(property);
    }
  }
}

3.#{}和${}的区别是什么?

#{} 会将参数进行预编译,就是jdbc 中的设置?号,然后预编译,设置参数

${} 会将参数直接替换,不会进行预编译

4.Mybatis的预编译

数据库接受到sql语句之后,需要词法和语义解析,优化sql语句,制定执行计划。这需要花费一些时间。如果一条sql语句需要反复执行,每次都进行语法检查和优化,会浪费很多时间。预编译语句就是将sql语句中的值用占位符替代,即将sql语句模板化。一次编译、多次运行,省去了解析优化等过程。

mybatis是通过PreparedStatement和占位符来实现预编译的。

mybatis底层使用PreparedStatement,默认情况下,将对所有的 sql 进行预编译,将#{}替换为?,然后将带有占位符?的sql模板发送至mysql服务器,由服务器对此无参数的sql进行编译后,将编译结果缓存,然后直接执行带有真实参数的sql。

预编译的作用:

  1. 预编译阶段可以优化 sql 的执行。预编译之后的 sql 多数情况下可以直接执行,数据库服务器不需要再次编译,可以提升性能。
  2. 预编译语句对象可以重复利用。把一个 sql 预编译后产生的 PreparedStatement 对象缓存下来,下次对于同一个sql,可以直接使用这个缓存的 PreparedState 对象。
  3. 防止SQL注入。使用预编译,而其后注入的参数将不会再进行SQL编译。也就是说其后注入进来的参数系统将不会认为它会是一条SQL语句,而默认其是一个参数。

5.一级缓存和二级缓存

缓存:合理使用缓存是优化中最常见的方法之一,将从数据库中查询出来的数据放入缓存中,下次使用时不必从数据库查询,而是直接从缓存中读取,避免频繁操作数据库,减轻数据库的压力,同时提高系统性能。

Mybatis里面设计了二级缓存来提升数据的检索效率,避免每次数据的访问都需要去查询数据库。

一级缓存是SqlSession级别的缓存:Mybatis对缓存提供支持,默认情况下只开启一级缓存,一级缓存作用范围为同一个SqlSession。在SQL和参数相同的情况下,我们使用同一个SqlSession对象调用同一个Mapper方法,往往只会执行一次SQL。因为在使用SqlSession第一次查询后,Mybatis会将结果放到缓存中,以后再次查询时,如果没有声明需要刷新,并且缓存没超时的情况下,SqlSession只会取出当前缓存的数据,不会再次发送SQL到数据库。若使用不同的SqlSession,因为不同的SqlSession是相互隔离的,不会使用一级缓存。

二级缓存是mapper级别的缓存:可以使缓存在各个SqlSession之间共享。当多个用户在查询数据的时候,只要有任何一个SqlSession拿到了数据就会放入到二级缓存里面,其他的SqlSession就可以从二级缓存加载数据。

你可能感兴趣的:(学习记录,mybatis,面试题,mybatis)