面试汇总-Mybatis-杂项

目录

1、Mybatis架构

2、Mapper接口的实现原理(JDK动态代理)

3、Mybatis缓存

3.1、一级缓存

3.2、二级缓存

3.3、mybatis的二级缓存有什么问题?

4、mybaits中的mapper的#{}和${}有什么区别?哪种可以防止sql注入?

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

6、每一个xml映射文件都会有一个对应的dao,Dao的工作原理是什么?

7、动态SQL

8、Mybatis延迟加载

9、核心对象的生命周期

9.1、SqlSessionFactoryBuilder

​​​​​​​9.2、​​​​​​​SqlSessionFactory

​​​​​​​9.3、SqlSession

​​​​​​​9.4、Mapper

​​​​​​​10、Mybatis插件原理(动态代理+责任链)

11、Mybatis设计模式


1、Mybatis架构

2、Mapper接口的实现原理(JDK动态代理)

        Mybatis使用JDK动态代理,会为Mapper接口生成一个代理Proxy对象,代理对象会拦截接口方法,转而执行MappedStatement所代表的SQL,然后将SQL执行结果返回。

3、Mybatis缓存

3.1、一级缓存

        sqlSession级别缓存,操作数据库时需要构建sqlSession对象,在对象中有一个HashMap用以存储缓存结构,保存在本地。

        当sqlSession做增加、修改、删除、commit()、close()任意一个操作时,都会清空一级缓存

3.2、二级缓存

  • 一级缓存缓存的是对象,二级缓存缓存的是数据。
  • Mapper级别缓存,多个sqlSession操作同一个mapper(xml映射文件)时,可共享同一个二级缓存,同一个接口里面的相同方法,都可以共享缓存
  • 进行缓存POJO类需要实现serializable接口,因为二级缓存有可能存储在内存中,也有可能存储在硬盘中,实现该接口是为了对数据进行序列化和反序列化操作。
  • SqlMapConfig.xml需要增加如下配置

        

  • 使用xml映射文件时,需要在相应xml文件中增加<cache>标签开启二级缓存;使用注解开发时,需要在相应dao接口上新增@CacheNameSpace注解以开启二级缓存。

        

  • 查询操作从二级缓存中取数据时,会将数据反序列化为一个新的对象,所以与一级缓存不同的是,多次从二级缓存中获取相同数据时,虽然数据相同,但是对象是不同的。
  • 注意:在开启二级缓存时,对于查询操作,只有在commit或close后才能将数据刷新到二级缓存;而对于增删改操作,默认会清空二级缓存(flushCache  = true)

3.3、mybatis的二级缓存有什么问题?

        二级缓存是保存在Mapper对象中的,现在有一张user表,两个Mapper文件,AMapper.xml和BMapper.xml,B修改了user表中的内容,A是感知不到的,那么再从A里查询如果用到了缓存,就是旧的数据。

4、mybaits中的mapper的#{}和${}有什么区别?哪种可以防止sql注入?

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

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

        动态sql标签:trim|where|set|foreach|if|choose|when|otherwise|bind;

        <resultMap>、<parameterMap>、<sql>、<include>、<selectKey>;

        其中<sql>为sql片段标签,通过<include>标签引入sql片段;

        <selectKey>为不支持自增的主键生成策略标签。

6、每一个xml映射文件都会有一个对应的dao,Dao的工作原理是什么?

Dao接口,即Mapper接口,没有实现类;接口名+方法名,唯一定位一个MappedStatement。

原理:

        JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,然后将sql执行结果返回。

接口的全限定名->就是xml映射文件中的namespace值。

接口的方法名->就是xml映射文件中的id值。

接口的方法参数->就是传递给sql的入参。

7、动态SQL

        动态sql可以让我们在映射文件中,根据不同的逻辑,动态拼接不同的SQL;

        trim|where|set|foreach|if|choose|when|otherwise|bind。

        原理:使用OGNL从sql参数对象中计算表达式的值,根据表达式的值动态拼接sql,以此来完成动态sql的功能。

8、Mybatis延迟加载

        仅支持 association(@One)关联对象和collection(@Many)关联对象的延迟加载

        延迟加载基于动态代理实现,当执行连表查询时,针对 association collection 的查询语句,不会立即去数据库查询,而是会生成关联目标类的代理对象,并保存起来。之后会在调用关联目标类对象的方法时,才会去执行关联对象涉及的查询语句。

​​​​​​​9、核心对象的生命周期

9.1、SqlSessionFactoryBuilder

        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);

        SqlSessionFactoryBuilder 是用来创建SqlSessionFactory的,可以被实例化、使用和丢弃,一旦创建了SqlSesionFactory,就不再需要它了。因此,SqlSessionFactoryBuilder实例的最佳作用域是方法作用域,也就是局部方法变量

​​​​​​​9.2、​​​​​​​SqlSessionFactory

        SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例。使用SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次(单例)。因此 SqlSessionFactory 的最佳作用域是应用作用域

​​​​​​​9.3、SqlSession

        每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域

​​​​​​​9.4、Mapper

        映射器是一些由你创建的、绑定你映射的语句的接口。映射器接口的实例是从 SqlSession 中获得的。因此从技术层面讲,任何映射器实例的最大作用域是和请求它们的 SqlSession 相同的。尽管如此,映射器实例的最佳作用域是方法作用域 也就是说,映射器实例应该在调用它们的方法中被请求,用过之后即可丢弃。

​​​​​​​10、Mybatis插件原理(动态代理+责任链)

对mybatis来说,插件就是拦截器,支持用插件对四大核心对象尽心拦截。

  1. 执行器Executor (update、query、commit、rollback等方法);
  2. SQL语法构建器StatementHandler (prepare、parameterize、batch、updates query等方 法);
  3. 参数处理器ParameterHandler (getParameterObject、setParameters方法);
  4. 结果集处理器ResultSetHandler (handleResultSets、handleOutputParameters等方法)

  1. 在创建Mybatis四大组件的时候,首先会生成四大组件的一个原生对象;
  2. 然后通过interceptorChain.pluginAll(target),调用拦截器链(插件)对原生对象进行拦截和功能加强,返回被重重代理(多插件)后的一个代理对象;
  3. 返回的代理对象可以拦截到目标对象的每一个执行。

以ParameterHandler的创建为例:

11、Mybatis设计模式

  • 工厂模式:SqlSessionFactory,产生SqlSession对象;
  • 建造者模式:SqlSessionFactoryBuilder,将构建逻辑从对象本身抽离出来,让对象只关注功能;
  • 单例模式:ErrorContext,线程级别单例,用于记录该线程的执行环境的错误信息;
  • 适配器模式:Log,对jdbc、log4j等各种日志框架的适配实现;
  • 代理模式:Mybatis实现的核心,如MapperProxy,采用jdk动态代理,为mapper生成一个具体的代理对象来实现Mybatis功能;
  • 模板方法模式:BaseExecutor,该类实现了大部分SQL执行的逻辑,然后再把几个方法交给几个子类来实现;
  • 装饰器模式:Cache

  以上内容为个人学习总结,仅供学习参考,如有问题,欢迎在评论区指出,谢谢!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值