1、什么是Mybatis?

  MyBatis是一个基于ORM的数据访问层/持久层的框架。

2.什么是ORM?

  ORM—对象关系映射
  我们在访问数据库的时候所编写的都是Java程序,Java程序只认识Java对象,而我们所访问的数据库大多数都是关系型数据库,那么这时Java程序要想访问关系型数据库,那么就需要将Java对象转换成关系型数据,才能被数据库认识。
  这时我们可以认为一个Java类就是关系型数据库中的一张数据表,Java类中的成员变量是数据库表中的一个列,Java类创建的Java对象就是数据库表中的一行记录。
  将Java对象对应成为数据库表记录的过程就是对象关系映射【ORM】。
  好处:当我们使用Java程序控制Java对象的时候,数据库中的数据表记录会随之变化。 【将原来通过java程序访问数据库表的操作,简化成通过java程序访问java对象】

3.Mybaits框架的优点:

  1. 与JDBC相比,减少了50%以上的代码量。
  2. MyBatis是最简单的持久化框架,小巧并且简单易学。
  3. MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重用。【从应用程序中分离SQL】
  4. 提供XML标签,支持编写动态SQL语句
  5. 提供映射标签,支持对象与数据库的ORM字段关系映射。

4.MyBatis框架的缺点:

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

5.MyBatis框架适用场合:

  MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案。
对性能的要求很高,或者需求变化较多的项目,如互联网项目,MyBatis将是不错的选择。

6. MyBatis工作原理?

  1)读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。
  2)加载SQL映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
  3)构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。
  4)创建会话对象:由会话工厂创建 SqlSession 对象,该对象中包含了执行 SQL 语句的所有方法。
  5)Executor 执行器:MyBatis 底层定义了一个 Executor 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
  6)MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。
  7)输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。
  8)输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程。
  注意:Executor 执行器执行SQL语句时,是根据SQL映射文件中对应元素的< insert>< update>< delete>< select>的id属性值去选择对应的sql语句,由于SQL映射文件中对应元素的< update>< delete>< select>的id属性值是数据访问接口的方法名,所以数据访问接口中的方法是不能重载的。

7.MyBatis执行SQL的两种方式

  用 Mapper 接口发送 SQL

 PersonMapper personMapper=sqlSession.getMapper(PersonMapper.class);
 personMapper.insertPerson(person);

  通过 SqlSession 的 getMapper 方法来获取一个 Mapper 接口,就可以调用它的方法了。因为 SQL映射 文件或者接口注解定义的 SQL 都可以通过“接口的全限定名+方法名”查找,所以 MyBatis 会启用对应的 SQL 进行运行,并返回结果。
  SqlSession 发送 SQL
  通过SqlSession对象的

int  insert(“接口的全限定名+方法名” ,  数据访问接口的方法的参数);
int  update(“接口的全限定名+方法名” ,  数据访问接口的方法的参数);
int  delete(“接口的全限定名+方法名” ,  数据访问接口的方法的参数);
<T>  selectOne(“接口的全限定名+方法名” ,  数据访问接口的方法的参数);
List<T>  selectList(“接口的全限定名+方法名” ,  数据访问接口的方法的参数);

  建议采用 SqlSession 获取 Mapper 的方式,理由如下:
  1.使用 Mapper 接口编程可以消除 SqlSession 带来的功能性代码,提高可读性,而 SqlSession 发送 SQL,需要一个 SQL id 去匹配 SQL,比较晦涩难懂。
  2.使用Mapper.selectPersonById(1)方式,IDE会提示错误和校验,而使用 sqlSession.selectOne(“com.wangxing.mybatis.mapper.PersonMapper.selectPersonById”,1)语法,只有在运行中才能知道是否会产生错误。

8.MyBatis的核心组件有哪些?以及各自的作用。

  SqlSessionFactoryBuilder:加载MyBatis核心配置来生成 SqlSessionFactory接口对象。

new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml"));

  SqlSessionFactory(工厂接口):生成 SqlSession
  SqlSession(会话):既可以发送 SQL 执行返回结果,也可以获取 Mapper 的接口.
  SQL Mapper(映射器): 1由一个 Java 接口和 XML 文件构成.
             2.由一个 Java 接口和注解构成.
             它负责发送 SQL 去执行,并返回结果。

9.MyBatis相关的配置文件

  MyBatis的核心配置文件[mybatis-config.xml]:配置配置参数、数据库连接、sql映射文件路径。
  注意常用的元素配置
  Sql映射文件{Mapper文件}【名称与数据访问接口一致】:配置编写SQL语句。
  注意配置元素的属性

10. Sql映射文件中配置元素的输入参数的属性配置和输出参数的属性配置。

  输入参数的属性–parameterType

Java程序中方法的参数Sql映射文件元素的parameterType属性
String、基本类型java.lang.String 【int/boolean…/java.lang.Integer】
POJO类型【对象型】包名+类名
集合类型【List,Map】List-java.util.List /[Map–java.util.HashMap/hashMap]

  数据访问接口中如何传递多个参数?
  第1种:可以将多个参数装载到一个java对象中。
  第2种:使用Map集合作为参数来装载
  第3种:用@param注解【不常用】
  例如:

List<PersonBean>  selectPersonTestIf(@Param("name")String name,
@Param("age")String age,@Param("address")String address);
在映射文件中使用#{0},#{1}代表传递进来的第几个参数
<select id="selectPersonTestIf"   resultType="PersonBean">
		select  * from t_person where 1=1  
		<if test="name != null  and  name !=''">
		   and per_name like #{name}
		</if>
<if test="age!= null  and  age!=''">
		   and per_age = #{1}
		</if>
<if test="address!= null  and  address!=''">
		   and per_address like #{2}
		</if>
	</select>

  输出参数的属性【select元素】—resultType与 resultMap属性


  成员变量的名称和表字段名不一致时,怎么办?
  1.sql映射文件中使用resultMap元素类配置成员变量的名称与表字段名的映射
  2.sql映射文件中对应元素的sql语句中用过设置别名实现成员变量的名称与表字段名的映射【列名 as 成员变量名称】。

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

  #{}表示一个占位符号,通过#{}可以实现PreparedStatement向占位符中设置值,自动
  进行java类型和jdbc类型转换。
  #{}可以有效防止sql注入。
  #{}可以接收简单类型值或pojo[javabean]属性值。 如果parameterType传输单个简单类型值,#{}括号中可以是value或其它名称。
  $ {}表示拼接sql字符串,通过${}可以将parameterType传入的内容拼接在sql中且不进行
  jdbc类型转换
   $ {}可以接收简单类型值或pojo[javabean]属性值,如果parameterType传输单个简单类型值,$ {}括号中只能是value。

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

select  * from t_person where 1=1 and per_name like  #{name}
List<PersonBean> personlist=mapper.selectPersonTestIf("%test%");
select * from t_person where 1=1 and per_name like ? 

select  * from t_person where 1=1 and per_name like  ${name}
List<PersonBean> personlist=mapper.selectPersonTestIf("’%test%’");
select * from t_person where 1=1 and per_name like ‘%test%

13. 为什么要使用动态SQL?常用的动态SQL有那些?执行原理?

  为了避免/减少在编写SQL语句是出现,忘记空格,丢失逗号/单引号的情况出现。
  Mybatis 提供了9种动态 SQL 标签:< if/>、< choose/>、< when/>、< otherwise/>、< trim/>、< where/>、< set/>、< foreach/>、< bind/>
  其执行原理为,使用OGNL的表达式,从SQL参数对象中计算表达式的值,根据表达式的值动态拼接SQL,以此来完成动态SQL的功能。

14. MyBatis实现一对一查询有几种方式?使用哪个元素?

  有2种方式 1.嵌套resultMap 2.嵌套select
  使用association元素【注意元素中的属性】

15. MyBatis实现一对多查询有几种方式?使用哪个元素?

  有2种方式 1.嵌套resultMap 2.嵌套select
  使用collection元素【注意元素中的属性】

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

  1.在SQL映射文件中编写SQL 语句的时候利用limit关键字分页

select * from student limit #{currIndex} , #{pageSize}

  2.使用拦截器分页【利用PageHelper分页插件】
   PageHelper分页插件的原理是利用拦截器去拦截指定的查询操作,然后在拦截到的查询操作中添加相关的分页逻辑,完成分页。
  3.RowBounds分页
  Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

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

  Mybatis是支持延迟加载;
  在Mybatis核心配置文件中设置;
  它的原理是,使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,把B查询上来,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。这就是延迟加载的基本原理。

18. Mybatis的一级、二级缓存?

  一级缓存是SqlSession级别的缓存。在操作数据库时需要构造sqlSession对象,在对象中有一个数据结构用于存储缓存数据。不同的sqlSession之间的缓存数据区域是互相不影响的。也就是他只能作用在同一个sqlSession中,不同的sqlSession中的缓存是互相不能读取的。
  二级缓存是mapper级别的缓存,多个SqlSession去操作同一个Mapper的sql语句,多个SqlSession可以共用二级缓存,二级缓存是跨SqlSession的。二级缓存的作用范围更大。
  开启二级缓存:
1.打开总开关
  在MyBatis的配置文件中加入:

<!--开启二级缓存-->
<setting name="cacheEnabled" value="true"/>

  2.在需要开启二级缓存的mapper.xml中加入caceh标签

<cache/>

  3.让使用二级缓存的POJO类实现Serializable接口

19.MyBatis与Hibernate有哪些不同?

  1.Mybatis和hibernate不同,Mybatis不完全是一个ORM框架【半自动】,因为MyBatis需要程序员自己编写Sql语句,不过mybatis可以通过XML或注解方式灵活配置要运行的sql语句,并将java对象和sql语句映射生成最终执行的sql,最后将sql执行的结果再映射生成java对象。
  2.Mybatis学习门槛低,简单易学,程序员直接编写原生态sql,可严格控制sql执行性能,灵活度高,非常适合对关系数据模型要求不高的软件开发,例如互联网软件、企业运营类软件等,因为这类软件需求变化频繁,一但需求变化要求成果输出迅速。但是灵活的前提是mybatis无法做到数据库无关性,如果需要实现支持多种数据库的软件则需要自定义多套sql映射文件,工作量大。
  3.Hibernate对象/关系映射能力强,数据库无关性好,对于关系模型要求高的软件(例如需求固定的定制化软件)如果用hibernate开发可以节省很多代码,提高效率。但是Hibernate的缺点是学习门槛高,要精通门槛更高,而且怎么设计O/R映射,在性能和对象模型之间如何权衡,以及怎样用好Hibernate需要具有很强的经验和能力才行。

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

  MySQL:Mapper文件insert语句设置useGeneratedKeys=“true” keyProperty=“id”

<insert  useGeneratedKeys="true"  keyProperty="id">
Sql语句
</insert>
Oracle:Mapper文件insert语句增加
<insert id=””  >
Insert into .......
<selectKey keyProperty="id" order="BEFORE" resultType="Integer">
select xxx_SEQ.nextval from dual
</selectKey>
</insert>

更多推荐

Mybatis面试题最新总结