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

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

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

#{}是预编译处理,${}是字符串替换。
Mybatis在处理#{}时,会将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值。
Mybatis在处理${}时,就是把${}替换成变量的值,使用#{}可以有效的防止SQL注入,提高系统的安全性。

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

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

4. 最佳实践中,通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法能重载吗?

Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement。在Mybatis中,每一个标签均会被解析为MappedStatement对象,标签内的sql会被解析为BoundSql对象。

8. 一对一、一对多、多对多的关联查询映射

有联合查询和嵌套查询。联合查询是几个表联合查询,只查询一次,通过在resultMap里面的association,collection节点配置一对一,一对多的类就可以完成
嵌套查询是先查一个表,根据这个表里面的结果的外键id,去再另外一个表里面查询数据,也是通过配置association,collection,但另外一个表的查询通过select节点配置。

9、请说一下MyBatis中缓存?

答:MyBatis中提供了两种缓存,一级缓存和二级缓存。通过缓存可以减少对数据库的访问,提高程序执行性能。
其中一级缓存又称SqlSession缓存,默认开启的,有效范围必须是同一个SqlSession对象,且每次缓存同一个方法中相同的SQL语句。在缓存时把SQL当做Key,查询的结果当做Value进行缓存。当关闭后释放缓存中内容。
而二级缓存又称SqlSessionFactory缓存,有效范围同一个SqlSessionFactory对象。默认是禁用状态,需要在映射文件中添加标签启用二级缓存。当SqlSession提交或关闭时把一级缓存的内容放入到二级缓存中。由于在项目SqlSessionFacotry是不关闭的,所以二级缓存内容默认是一直存在,二级缓存中放经常被查询,很少被修改的内容。
每次查询时先判断二级缓存,如果没有,再判断一级缓存,如果也没有,访问数据库,访问后把结果放入一级缓存中。

10 请说一下MyBatis执行原理?

答:
MyBatis是基于JDBC实现,提供了使用映射文件代替接口实现类的实现方案,并在里面提供了缓存的实现。
MyBatis在执行时首先需要加载MyBatis全局配置文件,可以通过Resouces类把配置文件转换为InputStream输入流对象。
然后通过MyBatis封装的DOM操作把InputStream转换为Configuration对象,使用Java对象存储XML配置文件的所有内容。
MyBatis是基于工厂设计模式创建SqlSession的,MyBatis底层会自动创建DefaultSqlSessionFactory实例,并在实例的全局属性configuration存储之前解析的Configuration对象。这时工厂对象创建完成。
然后通过工厂对象实例化SqlSession,在实例化时,MyBatis底层会自动创建默认的执行器SimpleExecutor和事务对象。事务对象默认使用的是ManagedTrasaction,但是在配置文件中多使用JDBCTransaction,使用JDBC API管理事务。
所以MyBatis底层规定了一个SqlSession对应一个事务对象和一个执行器。最后真是实例化时是创建的DefaultSqlSession。

后面就可以通过SqlSession接口对象创建接口的动态代理对象。在通过对象调用接口中方法,执行SQL。

执行完成后提交事务,在提交时会清空缓存,刷新Statement。

最后关闭对象,释放资源,所谓的释放资源就是把对象都赋值null。

11请说一下Mybatis中执行器?

答:
MyBatis的执行器都实现了Executor接口。作用是负责执行SQL语句,相当于JDBC中的Statement。
在MyBatis中执行器共分为三个类型:SimpleExecutor、ReuseExecutor、BatchExecutor。
其中SimpleExecutor是默认的执行器类型,每次执行SQL都需要预编译、设置参数、执行。
ReuseExecutor只预编译一次,复用Statement对象,然后设置参数,并执行。
BatchExecutor先预编译,批量执行时设置参数,最后统一提交给数据库执行。

在项目可以通过factory.openSession()方法参数设置执行器类型。通过枚举类型ExecutorType进行设置。
也可以在全局配置文件中通过中defaultExecutorType 进行全局设置。

12、resultType和resultMap之间的区别

image.png

13、一级缓存和二级缓存

{]FJ%OKEGQ1FD_~U((3S{Z2.png