Mybatis面试题

0.什么是Mybatis,优点,适用场合

是一个半自动化的持久层框架,内部封装了的jdbc,开发时候只需要关注sql,不用去浪费时间处理驱动连接等复杂的过程

优点:灵活,sql和java代码分开,便于管理,一个专注业务、一个专注数据,提供映射标签,支持编写动态sql,简单易学

对性能要求高,需求变化多的项目可以选择

1.Mybatis 中 #{}和 ${}的区别是什么?

#{}是预编译处理,${}是字符串替换。在处理#时候会将#{}替换为?将$替换为变量的值

#{}可以防止sql注入 提高安全性

既然${}会引起sql注入,为什么有了#{}还需要有${}呢?那其存在的意义是什么?

原生jdbc不支持占位符的地方可以使用${}进行取值

比如分表:按照年份分表

Select * from ${year}_salary

Select * from xx order by ${name} ${order}

#{}主要用于预编译,而预编译的场景其实非常受限,而${}用于替换,很多场景会出现替换,而这种场景可不是预编译

 

3. 说一下 Mybatis 的一级缓存和二级缓存?

一级缓存(本地缓存):SQLSession级别的缓存,作用域是SQlSession,默认开启一级缓存。

与数据库同一次会话期间查到的数据放到本地缓存中,以后需要获取相同的数据直接从缓存中取不用在继续查询

一级缓存失效情况:

1.sqlSession不同

2.sqlsession相同,查询条件不同

3. sqlsession相同,二次查询之间执行了增删改操作

4. sqlsession相同,手动清除了一级缓存

二级缓存(全局缓存):基于namespace级别的缓存,一个namespace对应一个二级缓存

第一次mapper调用查询会放到对应的mapper二级缓存中,第二次调用相同的namespace下mapper映射文件会去对应的二级缓存中取结果

进行增删改会清空

4. Mybatis 有哪些执行器(Executor)?

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生命周期范围内。

 

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

在Mybatis配置文件中,可以指定默认的ExecutorType执行器类型,也可以手动给DefaultSqlSessionFactory的创建SqlSession的方法传递ExecutorType类型参数。

5. Mybatis是如何进行分页的?Mybatis 分页插件的实现原理是什么?

 

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

分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

 

6. Mybatis 有几种分页方式?

 

Sql分页使用limit,拦截器分页,使用RowBounds对象进行分页,插件分页

7. RowBounds 是一次性查询全部结果吗?为什么?

不是,mybatis是对jdbc的封装,在jdbc驱动中有Fetch Size的配置,它规定每次最多从数据库查询多少条数据。

8. Mybatis 逻辑分页和物理分页的区别是什么?

物理分页是数据库本身提供的分页方式,效率高弥补了逻辑分页的缺点,不同数据库不同写法

逻辑分页是查询所有数据利用代码获取需要的数据,所有数据库统一写法,效率低消耗大量内存,有内存溢出的危险,对数据库压力大

9. Mybatis 如何编写一个自定义插件?

1.编写Interceptor实现类  2.使用@Intercepts注解完成插件签名 3.将写好的插件注册到全局配置文件中   

10. 通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?

Dao接口的工作原理是JDK动态代理,Mybatis运行时会使用JDK动态代理为Dao接口生成代理proxy对象,代理对象proxy会拦截接口方法,转而执行MappedStatement所代表的sql,

然后将sql执行结果返回。

Dao接口里的方法,是不能重载的,因为是全限名+方法名的保存和寻找策略。

11. Mybatis是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?

第一种:使用resultMap标签,逐一定义列名和对象属性名之间的映射关系

第二种:使用sql设置别名功能,将别名定义为属性名

列名和属性名有映射关系后,mybatis通过反射创建对象,将值反射给对象的属性并返回

12. Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理不?

动态sql可以让我们在Xml映射文件内,以标签的形式编写动态sql,完成逻辑判断和动态拼接sql的功能。

trim  where set foreach if choose when  bind

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

13. Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?

不同的Xml映射文件,如果配置了namespace,那么id可以重复

如果没有配置namespace,那么id不能重复

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

Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。

而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,

所以,称之为半自动ORM映射工具。

15. 一对一、一对多的关联查询 ?

<!--association  一对一关联查询  多对一 -->

<!--collection  一对多关联查询 -->

16. Mybatis是什么?与IBatis有什么区别?

1)ibatis本是apache的一个开源项目,2010年这个项目由apache software foundation 迁移到了google code,并且改名为mybatis。

2)Mybatis实现了接口绑定,使用更加方便,而iBatis不支持。

   注:Mybatis支持在接口上使用注解的方式,但是不建议使用,当遇到复杂SQL时该方式有局限性

3)对象关系映射的改进,效率更高,iBatis实现关系映射使用"子查询",而Mybatis不但支持子查询还增加了分步查询。

4)MyBatis采用功能强大的基于OGNL的表达式来消除其他元素。

5)SQL映射的语法区别,例如:动态SQL、传入参数、接收参数、存储过程等

17. Mybatis中在哪使用了命名空间?

在mapper映射文件中的mapper标签中的namespace属性上使用

18. mybatis 动态sql标签中循环标签中有哪些属性,各自的作用。

1)if 标签

if标签通常用于WHERE语句、UPDATE语句、INSERT语句中,通过判断参数值来决定是否使用某个查询条件、判断是否更新某一个字段、判断是否插入某个字段的值。

2) foreach 标签

foreach标签主要用于在sql中对集合进行迭代。也常用到批量删除、添加等操作中。

3) choose标签

MyBatis提供了choose 元素,按顺序判断when中的条件出否成立,如果有一个成立,则choose结束。

当choose中所有when的条件都不满则时,则执行 otherwise中的sql。

类似于Java 的switch 语句,choose为switch,when为case,otherwise则为default。

4)where标签

如果where标签包含的标签中有返回值的话,它就插入一个"where"。

此外,如果标签返回的内容是以AND 或OR 开头的,则它会剔除掉。

5)set 标签

使用set标签可以将动态的配置set关键字,和剔除追加到条件末尾的任何不相关的逗号。

6)trim标签

格式化输出,也可以通过trim标签设定或忽略前后缀来实现格式化输出

7)sql标签

当多种类型的查询语句的查询字段或者查询条件相同时,可以将其定义为SQL片段,方便调用。

8)include标签

用于引用定义的SQL片段

 

19. mybatis 动态sql中使用<where>标签与直接写where关键字有什么区别?

where标签为MyBatis的动态语句。where关键字是SQL语句中的where子句。

在mybatis动态SQL中,若直接用where子句的话可能会导致sql语法错误,查询失败。

20.如何获取自动生成的(主)键值?

将usegeneratedkeys设置为true,设置获取主键策略 keyproperty指定返回的主键值的属性

21.数据库连接中断怎么处理?

connection操作底层是一个循环处理操作,因此可以进行时间有关的参数:

max_idle_time : 表明最大的空闲时间,超过这个时间socket就会关闭

connect_timeout : 表明链接的超时时间

22.在开发过程中,经常遇到插入重复的现象,这种情况应该怎么解决

插入的过程一般都是分两步的:先判断是否存在记录,没有存在则插入否则不插入。如果存在并发操作,那么同时进行了第一步,然后大家都发现没有记录,最后在第二步的时候都插入了数据从而造成数据的重复。解决插入重复的思路可以是这样的:

下面场景,假设同时有三个线程:线程a、线程b、线程c,进行插入操作。

(1)判断数据库是否有数据,有的话则无所作为。没有数据的话,则进行下面第2步。
(2)大家都要去竞争锁,用redis当锁,即:redis set key,其中只有一个操作a会成功,其他并发的线程b和c会失败的。
(3)上面set key 成功的线程a,开始执行插入数据操作,无论是否插入数据成功,都在最后del key。【注】插入不成功可以多尝试几次,增加成功的概率。
(4)如果拿到锁的线程a没有插入成功,即便是尝试了数次也没有插入成功,此时定是系统出现了bug,应该搞一个短信报警机制,让研发人员及时发现问题。

 

23.事务执行过程中宕机的应对处理方式?

24.Java客户端中的一个connection问题?

25.在mapper中如何传递多个参数?

在对应的xml中使用#{param1} #{param2}到n排序

或者在dao层使用@param注解

有对应属性的实体类用实体类

或者用Map定义

26. Mybatis运行原理?

1)加载mybatis全局配置文件(数据源、mapper映射文件等),解析配置文件,MyBatis基于XML配置文件生成Configuration,和一个个MappedStatement(包括了参数映射配置、动态SQL语句、结果映射配置),其对应着<select | update | delete | insert>标签项。

2)SqlSessionFactoryBuilder通过Configuration对象生成SqlSessionFactory,用来开启SqlSession。

3)SqlSession对象完成和数据库的交互:

4)用户程序调用mybatis接口层api(即Mapper接口中的方法)

5)SqlSession通过调用api的Statement ID找到对应的MappedStatement对象

6)通过Executor(负责动态SQL的生成和查询缓存的维护)将MappedStatement对象进行解析,sql参数转化、动态sql拼接,生成jdbc Statement对象

7)JDBC执行sql。

8)借助MappedStatement中的结果映射关系,将返回结果转化成HashMap、JavaBean等存储结构并返回。

原文地址:https://www.cnblogs.com/kmcl1314/p/14416094.html