一、首先Mybatis是一个优秀的持久层ORM框架,它对jdbc的操作数据库的过程进行封装,使得开发者只需要关注SQL本身。不需要花费精力去处理一些重复和繁琐的步骤。最后通过java对象和statement中的sql进行映射生成最终执行的sql语句。最后由mysql框架执行sql并将结果映射成java对象并返回。
ORM:对象关系映射,简单点说就是将数据库中的表和java中的对象建立映射关系,可以让我们操作对象来间接的操作数据库。
半ORM:在查询关联对象或关联集合对象时,需要手动编写sql来完成。
二、MyBatis编程步骤
创建SqlSessionFactory
通过SqlSessionFactory创建SqlSession
通过Mapper接口执行数据库操作(实际还是调用的SqlSession的)
调用session.commit()提交事务
调用session.close关闭会话
三、MyBatis的工作原理
1.在DatasourceAutoConfiguration完成后,会去执行MybatisAutoConfiguration。该自动配置类会开启MybatisProperties类的初始化。会先读取MyBatis配置文件,用
加载映射文件。(SQL映射文件,其中配置了操作数据库的SQL语句)
构造会话工厂:通过MyBatis的环境等配置信息构建会话工厂SqlSessionFactory
创建会话对象:有会话工厂创建SqlSession对象,该对象包括了执行SQL语句的所有方法
Executor执行器:根据SqlSession传递的参数动态的生成需要执行的SQL语句,同时负责查询缓存的维护
Mappedstatement对象:用于存储要映射的SQL语句的id、参数等信息
输入参数映射:参数类型可以为Map、List等集合类型也可以使用基本数据类型和POJO类型
输出结果映射:和输入类似。
四、MyBatis的优点
基于SQL语句编程,相当灵活。SQL写在XML中,解除sql与程序代码的耦合,便于统一管理。提供XML标签,支持编写动态SQL语句,并可重用
消除了 JDBC 大量冗余的代码,不需要手动开关连接;
很好的与各种数据库兼容
能够与 Spring 很好的集成;
提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
五、MyBatis框架的缺点
SQL 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL 语句的功底有一定要求。
SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
MyBatis与Hibernate有哪些不同
MyBatis是一个半ORM框架,需要自己编写sql语句,灵活性高,但是需要自定义多套sql映射文件,工作量大
Hibernate数据库无关性好,节省代码,提高效率
六、#{}和${}的区别
#{}:是预编译处理,会把sql中的#{}替换为?,调用PreoaredStatement的set方法来赋值
{}替换为变量的值。
使用#{}可以有效的防止SQL注入,提高系统的安全性 。
七、当实体类的属性名和表中的字段名不一致如何处理
通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。
通过类映射字段名和实体类属性名的一一对应的关系
八、模糊查询like怎么编写
在Java代码中添加sql通配符
在sql语句中拼接通配符(但是会引起sql注入问题)
通常一个Xml映射文件,都会写一个Dao接口与之对应。那么Dao接口的工作原理是什么。
Dao接口就是Mapper接口。
九、接口的全限定名就是映射文件的namespace的值
接口的方法名就是映射文件中Mapper的Statement的id值
接口方法内的参数就是传递给sql的参数
Mapper接口是没有实现类的,当调用接口方法的时候,接口的全限定名+方法名拼接字符串作为key值,可以唯一定位一个MapperStatement。在MyBatis中,每一个、、、标签都会被解析为一个MapperStatement对象
十、Dao接口的方法,参数不同时,方法能重载吗
Mapper接口里的方法,是不能重载的,因为使用全限定名+方法名的保存和寻找策略。所以不能重载。
十一、Mapper接口的工作原理是JDK动态代理,MyBatis运行时会使用JDK动态代理为Mapper接口生成代理对象proxy,代理对象会拦截接口方法,转而执行MapperStatement所代表的sql,然后将sql执行结果返回。
十二、MyBatis是如何进行分页的以及分页插件的原理是什么
MyBatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页。可以在sql内直接书写带有物理分页的参数来完成物理的分页功能,或者使用分页插件来完成物理分页
分页插件的基本原理就是使用MyBatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect,添加对应的物理分页语句和物理分页参数。
十三、Mybati是如何将sql执行机构封装为对象并返回的?有哪些映射形式
使用标签,逐一定义数据库列名和对象属性名之间的映射关系。
使用sql列的别名功能,将列别名书写为对象属性名
有了列名和属性名的映射关系后,MyBatis通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的
十四、如何进行批量插入
十五、如何获取自动生成的主键值
使用JDBC内置方法
插入后查询获取
插入前查询获取主键
十六、如何在mapper中传递多个参数
Dao层函数
使用@param注解
多个参数封装成map
十七、MyBatis动态sql
MyBatis动态sql可以在Xml映射文件内,以标签的形式编写动态sql,执行原理是根据表达式的值完成逻辑判断并动态拼接sql功能
MyBatis提供了九种sql标签
trim
where
set
foreach
if
choose
when
otherwise
bind
十八、MyBatis的Xml映射文件中,不同的Xml文件id是否可以重复
如果配置了namespace那么id可以重复,要是没有配置namespace,id就不可以重复
十九、MyBatis实现一对一有几种方式
联合查询
几个表联合查询,只查询一次,通过配置collection节点
嵌套查询
先查一个表,再根据查出的id去另外一个表里查询数据,也是通过配置collection,但是另外一个表的查询通过select节点配置
二十、MyBatis是否支持延迟加载,以及如何实现
Mybatis仅支持association关联对象和collection关联集合对象的延迟加载。可以通过配置lazyLoadingEnabled来进行配置。
原理
使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。
二十一、MyBatis的缓存
一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空,默认打开一级缓存。
二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。默认不打开二级缓存,要开启二级缓存,使用二级缓存属性类需要实现 Serializable 序列化接口(可用来保存对象的状态),可在它的映射文件中配置 ;
缓存更新
进行增删改
调用清除方法
设置清除属性
二十二、MyBatis的接口绑定,以及实现方式
接口绑定:就是在MyBatis中任意定义接口,然后把接口里面的方法和SQL语句进行绑定,我们在使用的时候直接调用接口方法即可
实现方式
通过注解绑定
通过xml里面写sql语句来绑定,需要指定xml中namespace必须为接口的全路径名。
Mybatis的mapper接口调用时有哪些要求
Mapper接口的方法名和mapper.xml中sql的id相同
Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的parameterType 的类型相同
Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的resultType 的类型相同
Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径
二十三、Mybatis 的插件运行原理,以及如何编写一个插件。
Mybatis 仅可以编写针对 ParameterHandler、ResultSetHandler、StatementHandler、Executor 这 4 种接口的插件,Mybatis 使用 JDK 的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这 4 种接口对象的方法时,就会进入拦截方法,具体就是 InvocationHandler 的 invoke()方法,当然,只会拦截那些你指定需要拦截的方法。
编写插件:实现 Mybatis 的 Interceptor 接口并复写 intercept()方法,然后在给插件编写注解,指定要拦截哪一个接口的哪些方法即可,记住,别忘了在配置文件中配置你编写的插件。
二十四、预编译
定义
SQL预编译是指数据库驱动在发送SQL语句和参数给DBMS之前对SQL语句进行编译,这样DBMS执行SQL时,就不需要重现编译
预编译作用
可以优化SQL的执行。预编译后的大多数SQL可以直接运行,同时预编译语句对象可以重复利用。还可以防止SQL注入
二十五、MyBatis有哪些Executor执行器,他们之间的区别是什么
有三种基本的Executor执行器:SimpleExecutor、ReuseExxecutor、BatchExecutor
SimpleExecutor
每执行一次update或者select就开启一个Statement对象,用完就立即关闭
ReuseRxecutor
执行update或者select,以sql为key查找Statement对象。为了重复使用Statement对象
BatchExecutor
执行update,将所有sql都添加到批处理中,等待同一执行。其魂村了多个Statement对象。
二十六、当实体类中的属性名和表中的字段名不一样,怎么办
通过在查询的SQL语句中定义字段名的别名,让字段名和实体类的属性名一致
通过resultMap来映射字段名和实体类属性名的一一对应的关系
ResultType和ResultMap的区别
首先MyBatis在查询进行select映射的时候,返回类型可以用resultType也可以用resultMap,其中resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用。这两不能同时存在
在MyBatis进行查询映射的时候,其实查询出来的每一个属性都是放在一个对应的Map中,键是属性名、值是对应的值。
二十七、Mybatis的SqlSession下的四大对象
(1)Executor
调度执行StatementHandler、ParmmeterHandler、ResultHandler执行相应的SQL语句
(2)StatementHandler
使用数据库中Statement(PrepareStatement)执行操作,即底层是封装好了的prepareStatement;
(3)ParammeterHandler
处理SQL语句的参数
(4)ResultHandler
结果集ResultSet封装处理返回
二十八、Executor的分类
(1)SimpleExecutor 默认的,每次执行sql时,都会创建一个新的statement
(2)ReuseExecutor 用于预编译statement的
(3)BatchExecutor 用于批处理
PS:部分直接搬运来的,日后会加上自己的见解(等找到新工作,哭哭)