mybatis常见面试题汇总

1.什么是Mybatis?

Mybatis是一款持久层框架,半自动ORM映射工具.支持定制化sql,存储过程以及高级映射.避免了JDBC代码和手动设置参数和获取结果集,mybatis可以使用xml文件或者注解配置映射类,接口和POJO(普通老式java对象)

2.ORM是什么

  对象关系映射,解决关系型数据库数据和java对象映射关系的.通过映射将程序中的对象持久化到关系型数据库

3.为什么说Mybatis是半自动ORM映射 工具?它与全自动的区别在哪里?

  mybatis在查询关联对象或关联集合对象时,需要手动写sql完成,所以是半自动orm映射工具,全自动则不需要手写sql

4.传统JDBC开发存在的问题

   (1) 频繁创建数据库连接对象,释放造成系统浪费,影响性能. 使用连接池解决这问题但是需要自己实现连接池

   (2)sql语句,参数设置,结果集处理存在硬编码,代码不易维护,sql变动需要修改java代码

   (3) 使用perparedStatement 向占有位符号传参存在硬编码,

   (4) 结果集处理存在重复代码,处理麻烦

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

   mybatis-config.xml中配置数据库连接池,使用连接池管理数据可连接,解决频繁创建数据库连接对象

  mapper.xml中编写sql语句与java代码分离

  mybatis自动将java对象映射到sql语句

  mybatis自动将结果集映射大java对象

6.Mybatis的优点:

  优点: 基于sql语句编程,相对灵活,不会对数据库现有设计造成影响,sql写在xml文件里解除sql和java代码的耦合便于管理, 支持动态sql语句

           与jdbc相比减少了代码量,不需要手动开关数据库连接

           可以很好的与各种数据库兼容

           提供映射标签,支持对象与数据库的ORM字段关系映射,支持对象关系组件维护

           与spring很好的集成

7.Mybatis框架的缺点:

 缺点: sql语句编写量较大, 字段多关联表多时对开发人员sql编写功底要求高

          sql语句依赖数据库,导致数据库移植性差不能随意更换数据库

8.Mybatis框架适用场合:

   mysql专注sql本身是一个足够灵活的DAO层解决方案..  对性能要求高,需求变化较多的项目适用mybatis框架

9.MyBatis与Hibernate有哪些不同?

相同点

都是对jdbc的封装,都是持久层的框架,都用于dao层的开发。

不同点

映射关系

  • MyBatis 是一个半自动映射的框架,配置Java对象与sql语句执行结果的对应关系,多表关联关系配置简单
  • Hibernate 是一个全表映射的框架,配置Java对象与数据库表的对应关系,多表关联关系配置复杂

SQL优化和移植性

  • Hibernate 对SQL语句封装,提供了日志、缓存、级联(级联比 MyBatis 强大)等特性,此外还提供 HQL(Hibernate Query Language)操作数据库,数据库无关性支持好,但会多消耗性能。如果项目需要支持多种数据库,代码开发量少,但SQL语句优化困难。
  • MyBatis 需要手动编写 SQL,支持动态 SQL、处理列表、动态生成表名、支持存储过程。开发工作量相对大些。直接使用SQL语句操作数据库,不支持数据库无关性,但sql语句优化容易。

开发难易程度和学习成本

  • Hibernate 是重量级框架,学习使用门槛高,适合于需求相对稳定,中小型的项目,比如:办公自动化系统
  • MyBatis 是轻量级框架,学习使用门槛低,适合于需求变化频繁,大型的项目,比如:互联网电子商务系统

总结

MyBatis 是一个小巧、方便、高效、简单、直接、半自动化的持久层框架,

Hibernate 是一个强大、方便、高效、复杂、间接、全自动化的持久层框架。

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

     #{}是占位符,预编译处理; ${}是拼接符 字符串替换,没有预编译处理

     mybatis在处理#{}时,#{}传入参数时以字符串传入,会将sql中的#{}替换为?号,调用preparedStatement的set方法赋值

     mybatis在处理${}时,是原值传入,就是把${}替换成变量的值,相当于jdbc中的statement编译

     变量替换后#{}对应的变量会自动加上单引号,${}对应的变量不会加

     #{}可以有效防止sql注入,提高系统安全性,${}不能防止sql注入

    #{}的变量替换是在DBMS(数据库管理系统)中,${}变量替换在DBMS外

11.当实体类中的属性名和表中的字段 名不一样 ,怎么办 ?

     在sql语句中给字段定义别名,别名与实体类属性名一致

     定义reslutMap 映射字段名和实体类名属性名的对应关系

12.MyBatis编程步骤是什么样的?

     创建sqlsessionFactory

     通过sqlsessionFactory创建sqlsession

     通过sqlsession执行数据库操作

     session.commit提交事务

     session.close关闭会话

13.请说说MyBatis的工作原理

     读取mybatis-config.xml文件  配置文件配置了mybatis的运行环境的信息(数据库连接信息,mapper文件位置信息等)

     加载各个mapper.xml映射文件,映射文件中配置了操作数据库的sql语句  在mybatis配置文件中加载,可以加载多个映射文件每个文件对应一张表

      构造会话工厂 通过配置文件信息创建sqlsessionFactory

      通过会话工厂创建sqlsession对象  sqlsession中包含了执行sql语句的所有方法

     executor执行器  mybatis底层定义了一个excutor接口来操作数据库, 它根据sqlsession传递的参数动态的生成需要执行的slq语句,同时负责查询缓存的维护

     mappedStatement 对象,在executor执行方法中有一个mappedStatement类型的参数  该参数是对映射信息的封装,用于存储sql语句的id,参数等信息

     输入参数映射, 过程类似于jdbc对prepareStatement对象设置参数的过程

     输出记过映射  过程类似于jdbc对结果集的解析过程

14.MyBatis的功能架构是怎样的

     mybatis的功能架构主要分三层:

     api接口层:提供给外部使用的接口api  开发人员通过本地api操作数据库,接口层收到调用命令会调用数据处理层完成具体的数据处理

     数据处理层: 负责具体的sql查找,解析,执行和执行结果映射处理. 主要作用就是根据调用的请求完成一次数据库操作

     基础支撑层:负责最基础的功能支撑,包括连接管理,事务管理.配置加载和缓存处理

15.MyBatis的框架架构设计是怎么样

     mybatis的初始化会从配置文件中解析构造configuration类

     加载配置:配置主要来源于配置文件和java代码注释,  将sql的配置信息加载成一个个mappedStatement对象存储在内存中

     sql解析: api层收到调用请求时,会接收传入sql的id和传入对象,mybatis会根据sql的id找到对应的mappedStatement然后根据传入参数对mappedStatement进行解析,解析后得到要执行的sql语句和参数

     sql执行:  将最终的sql语句和参数执行得到操作数据库的结果

     结果映射: 将得到的结果根据映射配置进行转换并将最终结果返回

16.模糊查询like语句该怎么写?

     like   concat('%',#{},'%')  concat函数

     like  "%${}%"  无法防止sql注入

17.通常一个Xml映射文件,都会写一 个Dao接口与之对应,请问,这个 Dao接口的工作原理是什么?Dao接 口里的方法,参数不同时,方法能重 载吗?

     dao接口就是mapper接口,接口的全限定名就是映射文件中namespace的值, 接口的方法名就是mappedStatement的id,接口方法内的参数就是传递给sql的参数,  相当于mybatis功能架构的api接口层,调用方法时 接口全限定名+方法名作为key查找mappedstatement  

     dao接口中的方法时不能重载的  因为全限定名+方法名的保存和查找策略

     工作原理为jdk动态代理,mybatis运行时会使用jdk的动态dialing为dao接口生成代理对象  代理对象会拦截接口方法转而执行mappedStatement代表的sql语句并将结果返回

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

     mybatis使用RowBounds对象进行分页,它是针对resultset结果集执行的内存分页,而给物理分页,  可以在sql中直接写带有物理分页参数来完成物理分页也可以用插件完成

     分页插件的原理是使用mybatis提供的插件接口实现自定义插件,在插件的拦截方法内拦截待执行的sql然后重写sql  根据dialect方言 添加对应的物理分页语句和分页参数 例如: select * from user  重写后为  select u.* form(select * from user) u limit 0,10

19.Mybatis是如何将sql执行结果封 装为目标对象并返回的?都有哪些 映射形式?

     使用<resultmap> 标签  定义列名和对象属性名之间的映射关系

     利用sql 列别名  将别名对应对象的属性名  别名无所谓大小写  因为mybatis会忽略大小写

20.如何执行批量插入?

     使用foreach标签  标签主要属性有 item  index collection  open  separator  close

     item  每一个元素迭代的别名

     index  迭代过程中每次迭代的位置

     collection   要进行迭代的集合

     open  语句开始  "("

    close  语句结束  ")"

    separator  分隔符  ","

21.如何获取自动生成的(主)键值?

    支持主键自增的数据库  通过设置  useGeneratedKeys为true 和keyProperty  

    不支持主键自增的  使用selectKey标签获取

22.Mybatis动态sql有什么用?执行 原理?有哪些动态sql?

     作用: 可以让我们在xml映射文件中,以标签的形式编写动态sql  完成逻辑判断和动态拼接sql

     原理: 使用ognl从sql参数对象中计算表达式的值根据表达式的值动态拼接sql

     <trim><where><when><otherwise><foreach><if><chooose>

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

     <resultmap><include><sql><selectKey>动态标签等

24.Mybatis的Xml映射文件中,不同 的Xml映射文件,id是否可以重复?

     不同xml,如果配置了namespace id可以重复  没有配置namespace  id不能重复

     应为namespace+id是作为 mappedStatement的key使用的  没有namespace只剩id 重复会导致数据相互覆盖

25.MyBatis实现一对一有几种方式? 具体怎么操作的?

     联合查询  只查询一次 通过在resultmap中配置association节点配置一对一类  就可以完成

     嵌套查询  先查一个表根据结果的外键id 再去另一表里查数据  也是通过association配置  但另一个表的查询通过select属性配置

26.MyBatis实现一对多有几种方式, 怎么操作的?

    联合查询  通过在resultmap中配置collection 完成

    嵌套查询   先查一个表根据结果的外键id查另一个表  通过collection配置 配置属性select

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

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

     原理:  使用cglib创建目标对象的代理对象,当调用方法时进入拦截器方法 例如 a.getb().getName()  当拦截器发现a.getb为null值时, 会单独发送实现保存好的查询关联b对象的sql,把b查询出来在进行a.setb 然后完成a.getb.getname

28.Mybatis的一级、二级缓存:

     一级缓存:  基于perpetualCache的hashmap本地缓存,存储作用域为session  当session 刷新或者关闭后  session中左右的缓存清空  默认打开一级缓存

     二级缓存:  也是采用perpetualCache的hashmap本地缓存  不过作用域为maper(namespace)  并且可以自定义存储原 例如ehcache  默认二级缓存不打开.  如要开启 在mybatis配置文件中  配置 cacheenabled为true 并在mapper.xml文件中

  <cache></cache>使用二级缓存属性类需要实现serializable序列化接口,可在映射文件中配置<cache>

     缓存数据的更新机制  当某一个作用域进行了增删改操作后 默认该作用域下所有的select缓存都清空

29.什么是MyBatis的接口绑定?有哪 些实现方式?

     接口绑定  在mapper接口中任意定义接口然后把接口里面的方法和sql语句绑定,我们直接调用接口就可以了

     通过注解绑定  在接口方法上加@select @update等注解,里面包含sql语句来绑定

     通过xml中写sql绑定  指定xml中的namespace为接口的全限定名. 

    选取:sql语句简单时用注解 复杂时用xml

30.使用MyBatis的mapper接口调用时 有哪些要求?

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

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

    接口方法中输出参数类型和xml中每个sql的resulttype类型相同

    xml文件中namespace为mapper接口的类路径

31.简述Mybatis的插件运行原理,以 及如何编写一个插件。

     自定义插件:

     1实现interceptor接口

     2  实现响应方法  管阿金为intercep()方法中的拦截逻辑  需要增强的代码写这里

     3 在拦截器上加上注解  注解签名指定了要拦截的对象  拦截的方法 拦截的参数

     4 在mybatis配置文件中注册插件配置属性

     原理:

     在四大对象创建的时候  每个创建出来的对象不是直接返回的 而是通过interceptorChain.pluginAll(parameterHandler)

     获取到的所有的interceptor拦截器  拦截器调用interceptor.plugin(target)(返回target包装后的对象)

     插件机制, 饿哦们可以使用插件为目标对象创建一个代理对象 aop   插件可以为四大对象创建出代理对象  代理对象就可以拦截到四大对象的每一个执行

     四大对象  executor  执行操作  statementHandler  处理sql语句预编译和设置参数等  parameterhandler  设置预编译参数  resultsethandler  处理结果集

32.简述Mybatis的Xml映射文件和 Mybatis内部数据结构之间的映射 关系?

     mybatis将所有的xml配置信息都封装到configuration对象内.  在xml映射文件中<parametermap>标签会被解析为parametermap对象  每个子元素被解析为parametermapping对象. <resultmap>标签被解析为resultmap对象

     每个子元素被解析为resultmapping对象  <select><insert><update><delete> 标签被解析为mappedstatement对象  标签内的sql被解析为boundSql对象

33.Mybatis映射文件中,如果A标签 通过include引用了B标签的内容, 请问,B标签能否定义在A标签的后 面,还是说必须定义在A标签的前 面?

     mybatis解析xml文件是按照顺序进行解析的  但是被引用的b标签依然可以定义在任何地方,mybatis都可以正确解析识别

     原理:  mybatis解析a标签 发现a引用率b标签 但是b标签还没有解析时,mybatis会将a标签标记为为解析状态,继续解析剩余标签, 所有标签解析完后 mybatis会重新解析被标记为未解析的标签, 此时a就可以正常解析了

34.Mybatis是否可以映射Enum枚举 类?

    可以,mybatis可以映射任何对象到表的一列是上. 方式为 自定义一个typehandler 实现typehandler的setParameter和getresult方法

    typehandler的两个作用  完成从javatype到jdbctype的转换   完成jdbctype到javatype的转换  体现为setParameter和getresult方法  分别设置sql问号占位符参数和获取列查询结果

35.在mapper中如何传递多个参数

    顺序传参  #{0} #{1}  0,1代表参数的顺序

    @param注解传参  #{}中的名称对应@param修饰的名称

    map传参  #{}中的名称对应map的key

    javabean传参  #{}中的名称对应java对象的属性名

36.为什么需要预编译

    sql预编译是指数据库驱动在发送sql语句和参数给DBMS之前对sql语句进行编译 这样DBMS在执行sql时就不需要再进行编译了

    使用预编译可以在预编译阶段优化sql执行,预编译之后的sql基本都可以直接执行,DBMS不需要再次编译,越复杂的sql 编译的复杂度越大,预编译阶段可以合并多次操作为一次操作. 

    预编译语句对象可以重复使用,  一个sql预编译后产生的preparestatement对象缓存下来,下次对于同一个sql可以直接使用这个缓存的preparestate对象.  

    mybatis默认  会对所有的sql进行预编译

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

    三种基本的执行器   simpleExecutor,ResuseEXecutor, BatchExecutor

    simpleExecutor:每执行一次update或select 就开启一个statement对象,用完like关闭

    ResuseEXecutor: 执行update或select 以sql作为key查找statement对象  存在就用不存在则创建. 用完后不关闭statement对象, 放在map<string,statemtn>中, 可以重复使用statement对象

    BatchExecutor: 执行update  将所有sql都添加到批处理中,等待统一执行, 缓存了多个statement对象  每个statement对像都是添加到批处理后等到统一执行

    作用范围:executor这些特点,都限制到sqlsession的生命周期内

38.Mybatis中如何指定使用哪一种Executor执行器?

    在mybatis配置文件中  指定默认的executorType执行器类型

    手动给defaultsqlsessionfactory的创建sqlsession方法传递executor type类型参数

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值