Mybatis知识点

什么是Mybatis?

Mybatis是一个orm类型的半自动框架,执行了对JDBC的封装,是一个持久层框架,它可以通过XML文件或者注解来配置原生信息,不在需要去做更多繁琐重复的过程,如创建连接,加载驱动!

说说Mybatis 工作的流程

img

img

  1. 读取 MyBatis 配置文件:mybatis-config.xml 为 MyBatis 的全局配置文件,配置了 MyBatis 的运行环境等信息,例如数据库连接信息。
  2. 加载映射文件。映射文件即 SQL 映射文件,该文件中配置了操作数据库的 SQL 语句,需要在 MyBatis 配置文件 mybatis-config.xml 中加载。mybatis-config.xml 文件可以加载多个映射文件,每个文件对应数据库中的一张表。
  3. 构造会话工厂:通过 MyBatis 的环境等配置信息构建会话工厂 SqlSessionFactory。
  4. 创建会话对象:由会话工厂创建 SqlSession 对象,该象中包含了执行 SQL 语句的所有方法。
  5. Executor 执行器:MyBatis 底层定义了一个 Exector 接口来操作数据库,它将根据 SqlSession 传递的参数动态地生成需要执行的 SQL 语句,同时负责查询缓存的维护。
  6. MappedStatement 对象:在 Executor 接口的执行方法中有一个 MappedStatement 类型的参数,该参数是对映射信息的封装,用于存储要映射的 SQL 语句的 id、参数等信息。
  7. 输入参数映射:输入参数类型可以是 Map、List 等集合类型,也可以是基本数据类型和 POJO 类型。输入参数映射过程类似于 JDBC 对 preparedStatement 对象设置参数的过程。
  8. 输出结果映射:输出结果类型可以是 Map、 List 等集合类型,也可以是基本数据类型和 POJO 类型。输出结果映射过程类似于 JDBC 对结果集的解析过程

说一下Mybaits的优缺点和使用场合

优点:基于SQL语句编译,相当灵活,与JDBC相比,减少了50%的代码,很好的与各种数据库兼容,能够与Spring很好的集成,提供映射标签,支持对象关系组件维护!

缺点:SQL语句的编写工作量较大,尤其字段多,关联表多时,对开发人员编写SQL语句的功底有一定要求!SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库!

适用场合:MyBatis专注于SQL本身,是一个足够灵活的DAO层解决方案,对性能要求很高,或者需求变化较多的项目,如互联网项目!

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

  • #{}:是预编译处理。
  • ${}:是字符串替换。

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

在特殊使用场合,比如动态表名时可以使用${},但是要使用严格校验,防止SQL注入。

Mybatis中Like 使用的时候需要注意什么?

在xml写SQL的时候需要使用concat函数和#{}的方式来防止SQL注入;也要注意尽量不要全匹配,遵循最左匹配原则,否则当前SQL语句不会使用索引,会出现性能问题。

简述Mybatis的插件的运行原理,以及如何编写一个插件

Mybatis仅可以编写针对ParameterHandler、ResultSetHandler、StatementHandler、Executor这四种接口的插件,Mybatis使用JDK的动态代理,为需要拦截的接口生成代理对象以实现接口方法拦截功能,每当执行这四种接口对象的方法时,就会进入拦截方法,具体就是InvocationHandler的invoke()方法,当然,只会拦截那些你指定需要拦截的方法。

实现Mybatis的Interceptor接口并复写intercept()方法,返回再给插件编写注解,指定要拦截哪一个接口的哪些方法即可;最后在配置文件中配置你编写的插件。

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

  • 通过在查询的sql语句中定义字段名的别名,让字段名的别名和实体类的属性名一致!
  • 通过来映射字段名和实体类属性名的一一对应关系!

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

Dao接口即Mapper接口,接口的全限名,就是映射文件的namespace的值,接口的方法名,就是映射文件中Mapper的Statement的id值,接口方法内的参数,就是传递个sql的参数!因为mapper接口是没有实现类的,所以在调用方法时,需要拿全限定路径名称加上方法名作为key值。

方法名相同,参数不同时,会报错。

说一下resultMap和resultType

resultmap是手动提交,人为提交,resulttype是自动提交
MyBatis中在查询进行select映射的时候,返回类型可以用resultType,也可以用resultMap,resultType是直接表示返回类型的,而resultMap则是对外部ResultMap的引用,但是resultType跟resultMap不能同时存在。
在MyBatis进行查询映射时,其实查询出来的每一个属性都是放在一个对应的Map里面的,其中键是属性名,值则是其对应的值。

  1. 当提供的返回类型属性是resultType时,MyBatis会将Map里面的键值对取出赋给resultType所指定的对象对应的属性。所以其实MyBatis的每一个查询映射的返回类型都是ResultMap,只是当提供的返回类型属性是resultType的时候,MyBatis对自动的给把对应的值赋给resultType所指定对象的属性。
  2. 当提供的返回类型是resultMap时,因为Map不能很好表示领域模型,就需要自己再进一步的把它转化为对应的对象,这常常在复杂查询中很有作用。

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

多个参数封装成map,或者实体类。

Mybatis动态sql有什么用?执行原理?有哪些动态sql?

有九种动态sql标签:trim,where,set,foreach,if,choose,when,bind,otherwise。
Mybatis的动态sql可以在xml映射文件内,以标签的形式编写动态sql,执行原理是根据表达式的值,完成逻辑判断并动态拼接sql的功能!

什么是Mybatis的一级、二级缓存,如何开启?什么样的数据适合缓存?

一级缓存是基于PerpetualCache的hashmap本地缓存,其存储作用域为Session,当Session flush后,默认打开一级缓存。
二级缓存和一级缓存的机制是相同的,默认也是采用PerpetualCache的hashmap本地缓存,不过他的储存作用于在Mapper,而且可自定义存储源,要开启二级缓存,需要使用二级缓存属性类实现Serializable序列化的接口,可在它的映射文件中配置

缓存数据的更新机制,当某一个作用域(一级缓存session/二级缓存namespace)的进行了c/u/d操作后,默认该作用域下所有select中的缓存将被clear

什么是MyBatis的接口绑定?有哪些实现方式?

接口绑定就是在mybatis中任意定义接口,然后把接口里面的方法和sql语句绑定,我们直接调用接口方法就可以,这样比起原来sqlsession提供的方法我们可以有更加灵活的选择和设置。
有两种实现方式:

  1. 在接口的方法上面加上@select,@update等注解,里面包含sql语句来绑定。
  2. 通过xml里面写sql语句来绑定,在这种情况下,要指定xml映射文件里面的namespace必须为接口的全路径名。

当sql语句比较简单的时候,用注解绑定,当sql句比较复杂的时候,用xml绑定,一般使用xml绑定的比较多。