MyBatis面试汇总

目录

1.什么是MyBatis?

2.MyBatis的优缺点?

3.MyBatis是如何进行分页?分页插件的原理是什么?

4.MyBatis是如何将sql执行结果封装为目标对象并返回的?有哪几种映射方式?

5.说说MyBatis的缓存机制:

6.如何实现批量插入?

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

8.#{}和${}的区别是?


1.什么是MyBatis?

  • MyBatis是一个半ORM(Object Relation Mapping对象关系映射)框架、是支持自定义SQL、存储过程以及高级映射的持久层框架;
  • 内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建传输器、关闭资源等繁杂的过程。程序员直接编写写原生态sql,可以严格控制sql执行性能,灵活度高;
  • MyBatis可以使用xml或注解来配置和映射原生信息,将POJO映射成数据库中的记录,避免l几乎所有的JDBC代码和手动设置参数以及获取结果集的工作;

从执行sql到返回result的过程:通过xml或注解的方式将要执行的各种statement配置起来,并通过java对象和statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。

2.MyBatis的优缺点?

优点:

  1. 基于sql语句编程,相当灵活,不会对应程序或者数据库的现有设计造成任何影响,sql写在xml里,解除了SQL与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态sql语句,并可重用;
  2. 与JDBC相比,消除了JDBC大量冗余的代码,不需要手动开关连接;
  3. 很好的与各种数据库兼容
  4. 能够与Spring很好的集成;
  5. 提供映射标签,支持对象与数据库的ORM字段关系映射,提供对象关系映射标签,支持对象关系组件维护。

缺点:

  1. SQL语句主要依赖于数据库,导致数据库移植性差,不能随意更换数据库;
  2. SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的有一定要求。

3.MyBatis是如何进行分页?分页插件的原理是什么?

  • MyBatis使用RowBounds对象进行分页(是针对ResultSet结果集执行的内存分页,并非是物理分页)。可以在sql内直接拼写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页,比如:MySQL数据的时候,在原有SQL后面拼写limit。
  • 分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的SQL,然后重写SQL,根据dialect方言,添加对应的物理分页语句和物理分页参数。

4.MyBatis是如何将sql执行结果封装为目标对象并返回的?有哪几种映射方式?

  1. 使用标签,一一定义数据库列名和对象属性名之间的映射关系;
  2. 使用sql列的别名,将列的别名写为对象的属性名;

有了列名与属性名的映射关系后,MyBatis通过反射创建对象,同时使用反射给对象的属性一一赋值并返回,(找不到映射关系的属性,是无法赋值的)

5.说说MyBatis的缓存机制:

MyBatis整体

一级缓存localCache:

在应用运行过程中,我们有可能在一次数据库会话中,执行多次查询条件完全相同的sql,MyBatis提供了一次缓存的方案优化这部分场景,如果是相同的sql语句,会优化命中一级缓存,避免直接对数据库进行查询,提供性能。

每个sqlsession中持有了exectuor,每个Executor中有一个LocalCache。当用户发起查询时,Mybatis根据当前执行的语句生成MappedStatement,在Local Cache进行查询,如果缓存命中的话,直接返回结果给用户,如果缓存没有命中的话,查询数据库,结果写入Local Cache,最后返回结果给用户。具体实现类的类关系图如图所示:

 1.MyBatis一级缓存的生命周期和sqlsession一致;

 2.MyBatis一级缓存内部设计简单,只是一个没有容量限定的HashMap,在缓存的功能性上有所欠缺;

3. Mybatis的一级缓存最大范围是sqlsession内部,有多个sqlsession或者分布式的环境下,数据库写操作会引起脏数据,建议设定缓存级别为statement。

二级缓存:

在上文中提到的一级缓存中,其最大的共享范围就是一个sqlsession内部,如果多个sqlsession之间需要共享缓存,则需要使用到二级缓存。开启二级缓存后,会使用CachingExecutor装饰Executor,进入一级缓存的查询流程前,先在CachingExecutor进行二级缓存的查询,具体的工作流程如下所示。

 二级缓存开启后,同一个namespace下的所有操作语句,都影响着同一个Cache,即二级缓存被多个sqlsession共享,是一个全局的变量。

当开启缓存后,数据的查询执行的流程为:

二级缓存-->一级缓存-->数据库

  1. MyBatis的二级缓存相对于一级缓存来说,实现了sqlsession之间缓存数据的共享,同时粒度更加细,能够到namespace级别,通过cahce接口实现类不同的组合,对cache的可控性也更强;
  2. Mybatis在多表查询时,极大可能会出现脏数据,有设计上的缺陷,安全使用二级缓存的条件比较苛刻;
  3. 在分布式环境下,由于默认的MyBatis Cahce 实现都是基于本地的,分布式环境下必然会出现读取到脏数据,需要使用集中式缓存将Mybatis 的 Cache接口实现,有一定的开发成本,直接使用Redis、Memcached等分布式缓存可能成本更低,安全性也更高。

6.如何实现批量插入?

首先,创建一个简单的insert语句:
    <insert id="insertname">
         insert into names (name) values (#{value})   
    </insert>
然后在java代码中像下面这样执行批处理插入:
  list<string> names = new arraylist();    
    names.add("fred");
    names.add("barney");
    names.add("betty");
    names.add("wilma");

    // 注意这里 executortype.batch
    sqlsession sqlsession = sqlsessionfactory.opensession(executortype.batch);  
  try {
     namemapper mapper = sqlsession.getmapper(namemapper.class);
     for (string name : names) {
         mapper.insertname(name);
     }
     sqlsession.commit();
    }catch(Exception e){
     e.printStackTrace();
     sqlSession.rollback(); 
     throw e; 
    }
     finally {
         sqlsession.close();
    }

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

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

8.#{}和${}的区别是?

取值操作:#{属性值}、${属性值}

  • #取值采用占位符的方式,更加安全,能防止sql注入;
  • $一般使用场景,以字段为参数时使用;
  • 使用#号时候,默认为添加""号;
  • 能使用#{},绝不用${}
#{}${}
1.编译过程(占位符)动态解析->预编译处理->执行动态解析->字符串替换(编译)->执行
2.是否自动加入单引号对应的变量会自动添加不会
3.安全性可以有效的防止SQL注入,提高系统安全性不会
4.处理方式MyBatis在处理#{}时,会将sql中的#{}替换成?号,调用PreparedStatement的set方法来赋值MyBatis在处理${}时,是把${}替换成变量的值

(什么是sql注入?sql注入是一种常见的web安全漏洞,主要形成的原因是在数据交互中,前端的数据传入后台处理时,没有做到严格的判断,导致其传入的数据拼接到SQL语句中后,被当作SQL语句中的一部分执行,从而导致数据库受损)

9. MyBatis实现一对一有几种方式?如何操作?

有联合查询和嵌套查询两种

  1.   联合查询是几个表联合查询,只查询一次,通过resultMap里面配置association节点配置一对一的类就可以完成;
  2. 嵌套查询是先查一个表,根据这个表里面的结果的外键id,去再另外一个表里面查询数据,也是通过association配置,但另外一个表的查询通过select属性配置。         

10. MyBatis中比如UserMapper.java是接口,为什么没有实现类还能调用?

使用JDK动态代理+MapperProxy。本质上调用的是MapperProxy的invoke方法                                                                                                                                                                           

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值