#|mybatis面试题

mybatis面试题 一、基础知识 1.ORM
#|mybatis面试题
文章图片

4.动态sql语句
我们根据实体类的不同取值,使用不同的 SQL语句来进行查询。比如在 id如果不为空时可以根据id查询,如果username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。

="findByCondition" parameterType="student" resultType="student"> select * from student and id=#{id} and username=#{username}

5.#{}和${}的区别
#|mybatis面试题
文章图片

二、mybatis功能架构和执行流程 1.功能架构
#|mybatis面试题
文章图片

1.API接口层:提供给外部使用的接口API,开发人员通过这些本地API来操纵数据库。接口层一接收到调用请求就会调用数据处理层来完成具体的数据处理。
2.数据处理层:负责具体的SQL查找、SQL解析、SQL执行和执行结果映射处理等。它主要的目的是根据调用的请求完成一次数据库操作。
3.基础支撑层:负责最基础的功能支撑,包括连接管理、事务管理、配置加载和缓存处理,这些都是共用的东西,将他们抽取出来作为最基础的组件。为上层的数据处理层提供最基础的支撑。
2.执行流程
mybatis运行时要先通过resources把核心配置文件也就是mybatis.xml文件加载进来,然后通过xmlConfigBulider来解析,解析完成后把结果放入configuration中,并把它作为参数传入到build()方法中,并返回一个defaultSQLSessionFactory。我们再调用openSession()方法,来获取SqlSession,在构建SqlSession的同时还需要transaction和executor用于后续执行操作。
#|mybatis面试题
文章图片

三、mybatis一级缓存和二级缓存 1.概念
一级缓存 也叫做会话级缓存,生命周期仅存在于当前会话,不可以直接关关闭。但可以通过flushCache和localCacheScope对其做相应控制,1级缓存无法跨线程使用
二级缓存 应用级缓存,缓存对象存在于整个应用周期,而且可以跨线程使用,二级缓存有更高的命中率,适合缓存一些修改较少的数据。在流程上是先访问二级缓存,在访问一级缓存。
使用场景:静态表,字典表,权限表一般用来放在二级缓存中
2.两者区别
#|mybatis面试题
文章图片

3.一级缓存执行流程
#|mybatis面试题
文章图片

每个SqlSession中持有了Executor,每个Executor中有一个LocalCache。当用户发起查询时,MyBatis根据当前执行的语句生成MappedStatement,在Local Cache进行查询,如果缓存命中的话,直接返回结果给用户,如果缓存没有命中的话,查询数据库,结果写入Local Cache,最后返回结果给用户。
4.一级缓存特点
#|mybatis面试题
文章图片

5.二级缓存执行流程
在上文中提到的一级缓存中,其最大的共享范围就是一个SqlSession内部,如果多个SqlSession之间需要共享缓存,则需要使用到二级缓存。开启二级缓存后,会使用CachingExecutor装饰Executor,进入一级缓存的查询流程前,先在CachingExecutor进行二级缓存的查询,具体的工作流程如下所示。
#|mybatis面试题
文章图片

二级缓存开启后,同一个namespace下的所有操作语句,都影响着同一个Cache,即二级缓存被多个SqlSession共享,是一个全局的变量。
当开启缓存后,数据的查询执行的流程就是 二级缓存 -> 一级缓存 -> 数据库。
6.二级缓存特点
#|mybatis面试题
文章图片

7.Mybatis的mapper.xml配置文件
="select"> select * from user ="findUserById" parameterType="int" resultType="user"> where id = #{id} ="findAllOrders" resultMap="orders"> select * from orders ="id" keyProperty="id" order="AFTER" resultType="int"> select LAST_INSERT_ID() insert into user (username,sex,address) values(#{username},#{sex},#{address}) ="findUserBySexAndUsername" parameterType="User" resultType="user"> and sex = #{sex} and username like '%${username}%' ="findUserByIds" parameterType="QueryVo" resultType="user"> #{id}

四、mybatis用到的设计模式 1.建造者模式
概述 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示。相对于工厂模式会产出一个完整的产品,建造者模式应用于更加复杂的对象的构建,甚至只会构建产品的一个部分。
框架中应用 #|mybatis面试题
文章图片

#|mybatis面试题
文章图片

2.代理模式
代理模式可以认为是Mybatis的核心使用的模式,正是由于这个模式,我们只需要编写Mapper.java接口,不需要实现,由Mybatis后台帮我们完成具体SQL的执行。
当我们使用Configuration的getMapper方法时,会调用mapperRegistry.getMapper方法,而该方法又会调用mapperProxyFactory.newInstance(sqlSession)来生成一个具体的代理:
在这里,先通过T newInstance(SqlSession sqlSession)方法会得到一个MapperProxy对象,然后调用T newInstance(MapperProxy mapperProxy)生成代理对象然后返回。
非常典型的,该MapperProxy类实现了InvocationHandler接口,并且实现了该接口的invoke方法。
通过这种方式,我们只需要编写Mapper.java接口类,当真正执行一个Mapper接口的时候,就会转发给MapperProxy.invoke方法,而该方法则会调用后续的sqlSession.cud>executor.execute>prepareStatement等一系列方法,完成SQL的执行和返回。
3.装饰器模式
概念 装饰模式(Decorator Pattern) :动态地给一个对象增加一些额外的职责(Responsibility),就增加对象功能来说,装饰模式比生成子类实现更为灵活。
框架中应用 【#|mybatis面试题】在mybatis中,缓存的功能由根接口Cache(org.apache.ibatis.cache.Cache)定义。整个体系采用装饰器设计模式,数据存储和缓存的基本功能由PerpetualCache(org.apache.ibatis.cache.impl.PerpetualCache)永久缓存实现,然后通过一系列的装饰器来对PerpetualCache永久缓存进行缓存策略等方便的控制。

    推荐阅读