【Java八股文总结】之MyBatis

文章目录

  • MyBatis
    • 一、MyBatis基础
      • 1、什么是MyBatis?
        • Q:ORM是什么?
        • Q:为什么说MyBatis是半自动ORM映射工具?与全自动的区别是什么?
        • Q:动态SQL?
        • Q:JDBC的不足?MyBatis如何解决的?
      • 2、Hibernate和MyBatis的区别?
      • 3、MyBatis使用过程?生命周期?
      • 4、MyBatis中如何传递多个参数?
      • 5、实体类名和表中字段名不一样怎么办?
      • 6、MyBatis是否可以映射Enum枚举类?
      • 7、#{} 和 ${} 的区别(★★★★★)
      • 8、Mybatis是否支持延迟加载?
      • 9、MyBatis如何执行批量操作?
      • 10、MyBatis的一级、二级缓存
      • 11、MyBatis工作原理?
      • 12、MyBatis功能框架
      • 13、为什么Mapper接口不需要实现类?
      • 14、Mybatis都有哪些Executor执行器?
        • Q:Mybatis中如何指定使用哪一种Executor执行器?
      • 15、MyBatis插件运行原理?
      • 16、MyBatis分页查询怎么操作?分页插件的原理?
      • 17、MyBatis中的注解

MyBatis

一、MyBatis基础

MyBatis是 持久层(用于将数据保存到数据库的层)框架,用于简化JDBC开发。
JavaEE三层架构:表现层、业务层、持久层

1、什么是MyBatis?

  • Mybatis是一个 半ORM(对象关系映射)框架,它内部封装了JDBC,开发时只需要关注SQL语句本身,不需要花费精力去处理加载驱动、创建连接、创建statement等繁杂的过程。程序员直接编写原生态sql,可以严格控制sql执行性能,灵活度高。
  • MyBatis可以 使用XML或注解来配置和映射原生信息,将POJO映射成数据库中的记录,避免了几乎所有的JDBC代码和手动设置参数以及获取结果集。
  • SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
  • SQL语句依赖于数据库,导致 数据库移植性差,不能随意更换数据库。

Q:ORM是什么?

【Java八股文总结】之MyBatis_第1张图片
ORM(Object Relational Mapping),对象关系映射,是一种 为了解决关系型数据库数据与简单Java对象(POJO)的映射关系的技术。简单来说,ORM是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系型数据库中。

Q:为什么说MyBatis是半自动ORM映射工具?与全自动的区别是什么?

· Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。
· 而Mybatis在查询关联对象或关联集合对象时,需要手动编写SQL来完成,所以,被称之为半自动ORM映射工具。

Q:动态SQL?

SQL语句会随着用户的输入或外部条件的变化而变化,我们称为 动态SQL。
MyBatis中有一些支持动态SQL的标签,它们的原理是使用OGNL从SQL参数对象中计算表达式的值,根据表达式的值动态拼接SQL,以此来完成动态SQL的功能。
动态SQL可以使用if、choose(when、otherwise)、trim(where、set)、foreach等语句。

Q:JDBC的不足?MyBatis如何解决的?

JDBC: 硬编码(注册驱动,获取连接;SQL语句)、操作繁琐(手动设置参数、手动封装结果集)
MyBatis: 使用配置文件解决硬编码,参数和结果集封装自动完成。
MyBatis免除了几乎所有的JDBC代码以及设置参数和获取结果集的工作。
【Java八股文总结】之MyBatis_第2张图片

  1. 数据连接创建、释放频繁造成系统资源浪费从而影响系统性能,在mybatis-config.xml中配置数据连接池,使用连接池统一管理数据库连接
  2. sql语句写在代码中造成代码不易维护,将sql语句配置在XXXXmapper.xml文件中与java代码分离
  3. 向sql语句传参数麻烦,因为sql语句的where条件不一定,可能多也可能少,占位符需要和参数一一对应。Mybatis自动将java对象映射至sql语句
  4. 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。Mybatis自动将sql执行结果映射至java对象

2、Hibernate和MyBatis的区别?

相同点: 都是对jdbc的封装,都是应用于持久层的框架。
不同点
1)映射关系
MyBatis是一个 半自动映射的框架,配置Java对象与sql语句执行结果的对应关系,多表关联关系配置简单。
Hibernate是一个全表映射的框架,配置Java对象与数据库表的对应关系,多表关联关系配置复杂。
2)SQL优化和移植性
Hibernate对SQL语句封装,提供了日志、缓存、级联(级联比MyBatis强大)等特性,此外还提供HQL(Hibernate Query Language)操作数据库,数据库无关性支持好,但会多消耗性能。如果项目需要支持多种数据库,代码开发量少,但SQL语句优化困难。
MyBatis需要手动编写SQL,支持动态SQL、处理列表、动态生成表名、支持存储过程。开发工作量相对大些。直接使用SQL语句操作数据库,不支持数据库无关性,但sql语句优化容易。
3)MyBatis和Hibernate的适用场景不同
Hibernate是标准的ORM框架,SQL编写量较少,但不够灵活,适合于需求相对稳定,中小型的软件项目,比如:办公自动化系统。
MyBatis是半ORM框架,需要编写较多SQL,但是比较灵活,适合于需求变化频繁,快速迭代的项目,比如:电商网站。

3、MyBatis使用过程?生命周期?

【Java八股文总结】之MyBatis_第3张图片

  • SqlSessionFactoryBuilder
    一旦创建了SqlSessionFactory,就不再需要它了。 因此SqlSessionFactoryBuilder实例的生命周期只存在于方法的内部。
  • SqlSessionFactory
    SqlSessionFactory是用来创建SqlSession的,相当于一个数据库连接池,每次创建SqlSessionFactory都会使用数据库资源,多次创建和销毁是对资源的浪费。所以SqlSessionFactory是应用级的生命周期,而且应该是单例的。
  • SqlSession
    SqlSession相当于JDBC中的Connection,SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的生命周期是一次请求或一个方法。
  • Mapper
    映射器是一些绑定映射语句的接口。映射器接口的实例是从SqlSession中获得的,它的生命周期在sqlsession事务方法之内,一般会控制在方法级。

4、MyBatis中如何传递多个参数?

【Java八股文总结】之MyBatis_第4张图片

5、实体类名和表中字段名不一样怎么办?

① 通过在查询的 SQL语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
② 通过resultMap中的来映射字段名和实体类属性名的一一对应的关系。
如果是在MyBatisPlus中,还可以采用@TableName(“t_user”) :设置实体类所对应的表名、通过application.yml解决、MyBatis-Plus操作的表是由实体类决定的,表名遇下划线实体类字母变大写去掉下划线。

6、MyBatis是否可以映射Enum枚举类?

Mybatis当然 可以映射枚举类,不单可以映射枚举类,Mybatis可以映射任何对象到表的一列上。映射方式为自定义一个TypeHandler,实现TypeHandler的setParameter()和getResult()接口方法。
TypeHandler有两个作用,一是完成从javaType至jdbcType的转换,二是完成jdbcType至javaType的转换,体现为setParameter()和getResult()两个方法,分别代表设置sql问号占位符参数和获取列查询结果。

7、#{} 和 ${} 的区别(★★★★★)

① #{}是SQL中的参数占位符,预编译处理,MyBatis会将其替换为 ?可以防止SQL注入
② {}是Properties文件中的 变量占位符 ,没有预编译处理,可用在标签属性值和SQL内部,属于静态文本替换。
③ 使用时机:参数传递的时候使用:#{};表名或者列名不固定的情况下:{}会存在SQL注入问题。

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

9、MyBatis如何执行批量操作?

【Java八股文总结】之MyBatis_第5张图片

10、MyBatis的一级、二级缓存

  • 一级缓存:基于PerpetualCache的HashMap本地缓存,其存储作用域为SqlSession,各个SqlSession之间的缓存相互隔离,当Session flush或close 之后,该SqlSession中的所有Cache就将清空,MyBatis默认打开一级缓存。
    【Java八股文总结】之MyBatis_第6张图片
  • 二级缓存与一级缓存其机制相同,默认也是采用PerpetualCache,HashMap 存储,不同之处在于其存储作用域为Mapper(Namespace),可以在多个SqlSession之间共享,并且可自定义存储源,如Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现Serializable序列化接口(可用来保存对象的状态),可在它的映射文件中配置。
  • 【Java八股文总结】之MyBatis_第7张图片

11、MyBatis工作原理?

MyBatis的工作流程,按工作原理,可以分为两大步:生成会话工厂、会话运行。
【Java八股文总结】之MyBatis_第8张图片
【Java八股文总结】之MyBatis_第9张图片

  1. 读取MyBatis配置文件——mybatis-config.xml、加载映射文件——映射文件即SQL映射文件,文件中配置了操作数据库的SQL语句。最后生成一个配置对象。
  2. 构造会话工厂:通过MyBatis的环境等配置信息构建会话工厂 SqlSessionFactory。
  3. 创建会话对象:由会话工厂创建SqlSession对象,该对象中包含了执行SQL语句的所有方法。
  4. Executor执行器:MyBatis底层定义了一个Executor接口来操作数据库,它将根据SqlSession传递的参数动态地生成需要执行的SQL语句,同时负责查询缓存的维护。
  5. StatementHandler:数据库会话器,串联起参数映射的处理和运行结果映射的处理。
  6. 参数处理:对输入参数的类型进行处理,并预编译。
  7. 结果处理:对返回结果的类型进行处理,根据对象映射规则,返回相应的对象。

12、MyBatis功能框架

【Java八股文总结】之MyBatis_第10张图片
我们一般把Mybatis的功能架构分为3层:

  • API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
  • 数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
  • 基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。

13、为什么Mapper接口不需要实现类?

反射 + 动态代理 + 工厂模式。
【Java八股文总结】之MyBatis_第11张图片

14、Mybatis都有哪些Executor执行器?

【Java八股文总结】之MyBatis_第12张图片
Mybatis有3种基本的Executor执行器,SimpleExecutor、ReuseExecutor、BatchExecutor。

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

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

  • 在Mybatis配置文件中,在设置(settings)可以指定默认的ExecutorType执行器类型,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数,如SqlSession openSession(ExecutorType execType)。
  • 配置默认的执行器。SIMPLE就是普通的执行器;REUSE执行器会重用预处理语句(prepared statements);BATCH执行器将重用语句并执行批量更新。

15、MyBatis插件运行原理?

Mybatis会话的运行需要ParameterHandler、ResultSetHandler、StatementHandler、Executor这四大对象的配合,插件的原理就是在这四大对象调度的时候,插入一些我我们自己的代码。
【Java八股文总结】之MyBatis_第13张图片
Mybatis使用 JDK的动态代理,为目标对象生成代理对象。它提供了一个工具类Plugin,实现了InvocationHandler接口。
【Java八股文总结】之MyBatis_第14张图片
使用Plugin生成代理对象,代理对象在调用方法的时候,就会进入invoke方法,在invoke方法中,如果存在签名的拦截方法,插件的intercept方法就会在这里被我们调用,然后就返回结果。如果不存在签名方法,那么将直接反射调用我们要执行的方法。

16、MyBatis分页查询怎么操作?分页插件的原理?

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

  • 分页插件的原理是什么?
    分页插件的基本原理是 使用Mybatis提供的插件接口,实现自定义插件,拦截Executor的query方法。
    在执行查询的时候,拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
    举例: select * from student; ,拦截sql后重写为:select t.* from (select * from student) t limit 0, 10;

17、MyBatis中的注解

@Select、@Insert、@Update、@Delete、@Mapper、@MapperScan、@ResultMap

你可能感兴趣的:(Java学习乐园,mybatis,java,数据库)