MyBatis最新面试题汇总(只看这篇就够了)

MyBatis的优缺点

优点:
(1)基 于 SQL 语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL 写在 XML 里,解除 sql 与程序代码的耦合,便于统一管理;提供 XML标签,支持编写动态 SQL 语句,并可重用。

(2)与 JDBC 相比,减少了 50%以上的代码量,消除了 JDBC 大量冗余的代码,不需要手动开关连接;

(3)很好的与各种数据库兼容(因为 MyBatis 使用 JDBC 来连接数据库,所以只要JDBC 支持的数据库 MyBatis 都支持)。

(4)能够与 Spring 很好的集成;

(5)提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射标签,支持对象关系组件维护。

缺点:

(1)SQL 语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL 语句的功底有一定要求。

(2)SQL 语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。${}和#{}的区别是什么?

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

JDBC编程有哪些不足之处,Mybatis是如何解决这些问题的?

1) 数据库连接的创建、释放频繁造成系统资源浪费从而影响了性能,如果使用数据库连接池就可以解决这个问题。当然JDBC同样能够使用数据源。
解决:在SQLMapConfig.xml中配置数据连接池,使用数据库连接池管理数据库连接。

2) SQL语句在写代码中不容易维护,事件需求中SQL变化的可能性很大,SQL变动需要改变JAVA代码。解决:将SQL语句配置在mapper.xml文件中与java代码分离。

3) 向SQL语句传递参数麻烦,因为SQL语句的where条件不一定,可能多,也可能少,占位符需要和参数一一对应。解决:Mybatis自动将java对象映射到sql语句。

4) 对结果集解析麻烦,sql变化导致解析代码变化,且解析前需要遍历,如果能将数据库记录封装成pojo对象解析比较方便。解决:Mbatis自动将SQL执行结果映射到java对象。

当实体类中的属性名和表中的字段名不一样 ,怎么办 ?

方法一:通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。


	select order_id id, order_no orderno ,order_price price form orders where order_id=#{id};

方法二:通过来映射字段名和实体类属性名的一一对应的关系。

Mybatis编程步骤 ?

1、创建SQLSessionFactory

2、通过SQLSessionFactory创建SQLSession

3、通过SQLSession执行数据库操作

4、调用session.commit()提交事物

5、调用session.close()关闭会话

模糊查询再MyBatis中怎么写

一般模糊查询都是通过 like %xx% 这种形式来查询的,xx是前端传过来的查询变量,在MyBatis中推荐使用字符串拼接函数的形式来使用,这样出错的可能性较小。


      and user_name like concat('%',#{xx,jdbcType=VARCHAR},'%')
使用Mybatis的mapper接口调用时候有哪些要求?

1、Mapper接口方法名和Mapper.xml中定义的每个SQL的id相同;

2、 Mapper接口方法的输入参数类型和mapper.xml中定义的每个sqlparameterType类型相同

3、 Mapper接口方法的输入输出参数类型和mapper.xml中定义的每个sql的resultType的类型相同

4、 Mapper.xml文件中的namespace,就是接口的类路径。

MyBatis中的Mapper只有接口,那实现类是怎么生成的?当我们调用Mapper接口中的某个方法时,这个方法是怎么跟Mapper映射文件中的SQL语句对应起来的。

在使用MyBatis的时候我们只需要定义Mapper接口进行了,具体的Mapper接口实现是通过动态代理的方式生成的。

MyBatis在启动的时候会为每个Mapper映射文件指定一个MapperProxyFactory类,这个类是MapperProxy的工厂类,当我们调用sqlSession1.getMapper时,就会使用
MapperProxyFactory来生成动态代理类。生成的动态代理类代理了Mapper的所有接口。

CbondissuerMapper cbondissuerMapper10 = sqlSession1.getMapper(CbondissuerMapper.class);

下面来回答第二个问题,Mapper接口中的方法是怎么和映射文件中的SQL匹配起来的。

上面提到,Mapper接口的实现类是通过动态代理生成的,熟悉动态代理的应该知道调用Mapper接口的任何接口方法都会调到InvocationHandler接口的
invoke方法,在这里也就是MapperProxy的invoke方法。因为MapperProxy实现了InvocationHandler接口。

查看MapperProxy的invoke方法的源代码,我们会发现接口方法调用可具体的SQL是通过一个叫做MapperStatement的对象关联起来的。

MyBatis在启动时会将Mapper文件中的每一个 标签均会被解析为MappedStatement对象,标签内的sql会被解析为BoundSql对象。

一级、二级缓存

1、一级缓存: 基于 PerpetualCache 的 HashMap 本地缓存,其存储作用域为 Session,当 Session flush 或 close 之后,该 Session 中的所有 Cache 就将清空。

2、二级缓存与一级缓存其机制相同,默认也是采用 PerpetualCache,HashMap 存储,不同在于其存储作用域为 Mapper(Namespace),并且可自定义存储源,如 Ehcache。要开启二级缓存,你需要在你的 SQL 映射文件中添加一行:

3、对于缓存数据更新机制,当某一个作用域(一级缓存 Session/二级缓存Namespaces)的进行了C/U/D 操作后,默认该作用域下所有 select 中的缓存将被 clear。

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

Dao接口,就是人们常说的Mapper接口,接口的全限名,就是映射文件中的namespace的值,接口的方法名,就是映射文件中MappedStatement的id值,接口方法内的参数,就是传递给sql的参数。Mapper接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为key值,可唯一定位一个MappedStatement,举例:com.mybatis3.mappers.StudentDao.findStudentById,可以唯一找到namespace为com.mybatis3.mappers.StudentDao下面id = findStudentById的MappedStatement。在Mybatis中,每一个