Mybatis 面试题

1、MyBatis的编程步骤 

     创建SqlSessionFactory

    通过SqlSessionFactory创建SqlSession

    通过SqlSession执行数据库操作

   调用session.commit()提交事务

   调用session.close()关闭事务

2、#{}和${}的区别是什么? 

    #{}是预编译处理,${}是字符串替换;

   MyBatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;

   MyBatis在处理${}时,会把时,会把{}替换成变量的值

   使用#{}可以有效防止SQL注入,提高系统的安全性

3、Xml映射文件中,除了常见的select|insert|updae|delete标签之外,还有哪些标签? 

     <resultMap>、<parameterMap>、<sql>、<include>、,加上动态sql的9个标签,      trim|where|set|foreach|if|choose|when|otherwise|bind等

4、JDBC编程有哪些不足之处,MyBatis是如何解决这些问题的? 

    JDBC编程的不足之处 

   1) 数据库链接创建、释放频繁造成系统资源浪费从而影响系统性能,如果使用数据库链接池可解决此问题。

   2)Sql语句写在代码中造成代码不易维护,实际应用sql变化的可能较大,sql变动需要改变java代码。

   3)向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。

   4)对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。

MyBatis的解决方案 

  1)在SqlMapConfig.xml中配置数据链接池,使用连接池管理数据库链接。

  2)将Sql语句配置在XXXXmapper.xml文件中与java代码分离。

  3)Mybatis自动将java对象映射至sql语句。

  4)Mybatis自动将sql执行结果映射至java对象。

5、MyBatis的优缺点 

    优点 

     易于上手和掌握

    Sql写在xml里面,便于统一管理和优化

    减少Sql与程序代码的耦合

    提供xml标签,支持动态Sql编写

缺点 

   Sql工作量大,尤其是字段多,关联表多时,更是如此

   Sql依赖于数据库,导致数据库移植性差

   由于xml里面标签id必须唯一,导致DAO中方法不支持方法重载。所以dao层必须是接口

6、使用MyBatis的mapper接口调用时有哪些要求? 

    Mapper接口方法名和mapper.xml中定义的每个sql的id相同

    Mapper接口方法的输入参数类型和mapper.xml中定义的每个sql 的parameterType的类型相同

   Mapper接口方法的输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

   Mapper.xml文件中的namespace即是mapper接口的类路径

7、Mybatis和Hibernate的区别 

    Hibernate是全自动ORM映射工具,而Mybatis是半自动ORM映射工具 

    hibernate完全可以通过对象关系模型实现对数据库的操作,拥有完整的JavaBean对象与数据库的映射结构来自动生成sql。

   而mybatis仅有基本的字段映射,对象数据以及对象实际关系仍然需要通过手写sql来实现和管理。

   Hibernate数据库移植性远大于mybatis

  hibernate拥有完整的日志系统,mybatis则欠缺一些。 

  hibernate日志系统非常健全,涉及广泛,包括:sql记录、关系异常、优化警告、缓存提示、脏数据警告等;而mybatis则除了基本记录功能外,功能薄弱很多。

mybatis相比hibernate需要关心很多细节

sql直接优化上,mybatis要比hibernate方便很多。

8、Mybatis是如何进行分页的?分页插件的原理是什么?

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10

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

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

Mybatis有三种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor

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

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

 

简单的说一下MyBatis的一级缓存和二级缓存?

一级缓存:Mybatis首先去缓存中查询结果集,如果没有则查询数据库,如果有则从缓存取出返回结果集就不走数据库。Mybatis内部存储缓存使用一个HashMap,key为hashCode+sqlId+Sql语句。value为从查询出来映射生成的java对象

Mybatis的二级缓存即查询缓存,它的作用域是一个mapper的namespace,即在同一个namespace中查询sql可以从缓存中获取数据。二级缓存是可以跨SqlSession的。

无事务前提,dao每个sql操作都是一个sqlSession实例在进行操作不可能共用一级缓存。在有事务前提下,同个事务内使用一个sqlSession实例所以这个事务内的所有sql会共用一级缓存。

       1一级缓存: 基于PerpetualCache 的 HashMap本地缓存,其存储作用域为 Session,当 Session flush  close 之后,该Session中的所有 Cache 就将清空

  2)二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。

  3). 对于缓存数据更新机制,当某一个作用域(一级缓存Session/二级缓存Namespaces)的进行了 C/U/D 操作后,默认该作用域下所有 select 中的缓存将被clear。

MyBatis架构

Configuration   MyBatis所有的配置信息都保存在Configuration对象之中,配置文件中的大部分配置都会存储到该类中

SqlSession   作为MyBatis工作的主要顶层API,表示和数据库交互时的会话,完成必要数据库增删改查功能

Executor   MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护

StatementHandler  封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数等

ParameterHandler  负责对用户传递的参数转换成JDBC Statement 所对应的数据类型

ResultSetHandler  负责将JDBC返回的ResultSet结果集对象转换成List类型的集合

TypeHandler  负责java数据类型和jdbc数据类型(也可以说是数据表列类型)之间的映射和转换

MappedStatementMappedStatement  维护一条<select|update|delete|insert>节点的封装

SqlSource 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回

BoundSql  表示动态生成的SQL语句以及相应的参数信息

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值