1.什么是Mybatis
- Mybatis是一个半ORM(对象关系映射)框架,内部封装JDBC,无需处理驱动加载、创建连接、创建statement等过程,只关注sql。
- Mybatis使用Xml或注解配置和映射原生信息,将 POJO 映射成数据库中的记录,避免 JDBC 代码和手动设置参数以及获取结果集。
- 通过 xml 文件或注解的方式配置要执行的各种 statement ,并将java 对象和statement中 sql 的动态参数进行映射生成最终执行的 sql 语句,最后由 mybatis 框架执行 sql 并将结果映射为 java 对象并返回。(从执行 sql 到返回 result 的过程)
2.Mybatis的优点
- 基于sql编程,相较灵活;通过xml编写sql,解除与程序代码得耦合性;提供 XML 标签,支持编写动态 SQL 语句,并可重用。
- 由于内部封装JDBC,因此只要与JDBC兼容的数据库,其都能兼容;
- 能与Spring很好地集成;
- 提供映射标签,支持对象与数据库的 ORM 字段关系映射;提供对象关系映射标签,支持对象关系组件维护;
3.Mybatis的缺点
- 当字段和关联表多时,SQL工作量大;
- 依赖于数据库,导致数据库移植性差,不能随意更换数据库;
4.Mybatis使用场景
- 专注于 SQL 本身, 是一个足够灵活的 DAO 层解决方案。
- 对性能的要求很高,或者需求变化较多的项目,如互联网项目
5.Mybatis与hiberate的区别
- Mybatis 是一个 半ORM 框架,它需要程序员自己编写Sql 语句。
- Mybatis 直接编写原生态 sql, 可以严格控制 sql 执行性能, 灵活度高, 非常适合对关系数据模型要求不高的软件开发, 因为这类软件需求变化频繁, 一但需求变化要求迅速输出成果。但是灵活的前提是 mybatis 无法做到数据库无关性, 如果需要实现支持多种数据库的软件,则需要自定义多套 sql 映射文件,工作量大(依赖于数据库)。
- Hibernate 对象/关系映射能力强, 数据库无关性好, 对于关系模型要求高的软件,如果用 hibernate 开发可以节省很多代码, 提高效率(不依赖于数据库)。
6.#{}与${}符号区别
- #{}是预编译处理, ${}是字符串替换。
- Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的set 方法来赋值;
- Mybatis 在处理${}时,就是把${}替换成变量的值。
- 使用#{}可以有效的防止 SQL 注入,提高系统安全性。
- SQL注入:用户输入中嵌入恶意的SQL代码片段,从而在执行SQL查询时改变了原本预定的逻辑
- 预编译阶段数据库驱动会分析SQL语法,并对参数进行类型检查和转义处理。具体的参数值传给已经编译好的SQL模板执行,而不是直接拼接SQL字符串
7.实体类属性名与表中字段名不同,怎么办?
- 通过在查询的 sql 语句中定义字段名的别名,让字段名的别名和实体类的属性名一致
- 通过<resultMap>来映射字段名和实体类属性名的一一对应的关系
8.模糊查询like语句如何写
- 在 Java 代码中添加 sql 通配符
- 在 sql 语句中拼接通配符, 会引起 sql 注入(使用数据库特定安全函数,
CONCAT()
和ESCAPE
关键词来确保特殊字符不会引起SQL注入问题)
9.在Mybatis中,通常一个xml文件都会写一个dao接口与之对应;dao接口工作原理,dao接口中方法参数不同时,如何重载?
Dao 接口即 Mapper 接口。接口的全限名,就是映射文件中的 namespace 的值; 接口的方法名, 就是映射文件中 Mapper 的 Statement 的 id 值; 接口方法内的参数, 就是传递给 sql 的参数。
Mapper 接口是没有实现类的,当调用接口方法时,接口全限名+方法名拼接字符串作为 key 值,可唯一定位一个 MapperStatement。在 Mybatis 中, 每一个<select>、<insert>、<update>、<delete>标签, 都会被解析为一个MapperStatement 对象。如:
com.mybatis3.mappers.StudentDao.findStudentById, 可以唯一找到 namespace 为com.mybatis3.mappers.StudentDao 下面 id 为findStudentById 的 MapperStatement。
Mapper 接口里的方法,是不能重载的,因为是使用 全限名+方法名 的保存和寻找策略。Mapper 接口的工作原理是 JDK 动态代理, Mybatis 运行时会使用 JDK动态代理为 Mapper 接口生成代理对象proxy, 代理对象会拦截接口方法, 转而执行 MapperStatement 所代表的 sql, 然后将 sql 执行结果返回。
10.Mybatis如何进行分页,分页插件原理是什么?
Mybatis 使用 RowBounds 对象进行分页, 它是针对 ResultSet 结果集执行的内存分页,而非物理分页。可以在 sql 内直接书写带有物理分页的参数来完成物理分页功能, 也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用 Mybatis 提供的插件接口, 实现自定义插件, 在插件的拦截方法内拦截待执行的 sql,然后重写 sql,根据 dialect 方言(处理不同数据库的抽象接口),添加对应的物理分页语句和物理分页参数。
11.Mybatis是如何将SQL执行结果封装成目标对象并返回的,有哪些映射形式。
有了列名与属性名的映射关系后, Mybatis 通过反射创建对象, 同时使用反射给对象的属性逐一赋值并返回, 那些找不到映射关系的属性, 是无法完成赋值的。
12.如何获取自动生成的主键值?
insert 方法总是返回一个 int 表示插入的行数。 如果采用自增长策略,自动生成的键值在 insert 方法执行完后可以被设置到传入的参数对象中。
13.Mapper中如何传递多个参数
- dao接口中添加多个参数
- 使用@Param()注解
- 多个参数封装成Map
14.动态SQL有哪些、作用、执行原理
Mybatis 提供了 9 种动态 sql 标签:trim | where | set | foreach | if | choose | when | otherwise | bind 。
Mybatis 动态 sql 可以在 Xml 映射文件内,以标签的形式编写动态 sql,执行原理是根据表达式的值 完成逻辑判断并动态拼接 sql 的功能。
15.Mybatis的xml映射文件中,不同的xml文件id是否可以重复
不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;
16.为什么Mybatis是半ORM,它与全自动的区别在哪
Hibernate属于全自动ORM映射工具,使用Hibernate查询关联对象或者关联集合对象时,可以根据对象关系模型直接获取,所以它是全自动的。而Mybatis在查询关联对象或关联集合对象时,需要手动编写sql来完成,所以,称之为半自动ORM映射工具。
17.Mybatis是否支持延迟加载,它的实现原理是什么
Mybatis仅支持association(一对一查询)关联对象和collection(一对多查询)关联集合对象的延迟加载。在Mybatis配置文件中,可以配置是否启用延迟加载lazyLoadingEnabled=true|false。
延迟加载的基本原理:使用CGLIB创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用a.getB().getName(),拦截器invoke()方法发现a.getB()是null值,那么就会单独发送事先保存好的查询关联B对象的sql,查询出B,然后调用a.setB(b),于是a的对象b属性就有值了,接着完成a.getB().getName()方法的调用。类似于Mybatis,Hibernate这样的ORM框架,支持延迟加载的原理都是一样的。
18.Mybatis中的一级缓存和二级缓存
一级缓存:
一级缓存基于sqlSession默认开启,在操作数据库时需要构造SqlSession对象,在对象中有一个HashMap用于存储缓存数据。不同的SqlSession之间的缓存数据区域是互相不影响的。当在同一个sqlSession中执行两次相同的sql语句时,第一次执行完毕会将数据库中查询的数据写到缓存(内存),第二次查询时会从缓存中获取数据,不再去底层数据库查询,从而提高查询效率。当一个SqlSession结束后该SqlSession中的一级缓存也就不存在了。
注意:如果SqlSession执行了DML操作(增删改),并且提交到数据库,MyBatis则会清空SqlSession中的一级缓存,这样做的目的是为了保证缓存中存储的是最新的信息,避免出现脏读现象。
二级缓存:
二级缓存是mapper级别的缓存。使用二级缓存时,多个SqlSession使用同一个Mapper的sql语句去操作数据库,得到的数据会存在二级缓存区域,它同样是使用HashMap进行数据存储。执行相同SQL缓存原理通一级缓存。需手动开启Mapper的namespace下的二级缓存。
19.使用MyBatis的mapper接口调用时,需要遵循的要求
- 方法名与SQL ID映射
- 参数类型匹配
- 结果类型匹配
- 命令空间关联
20.简述Mybatis插件运行原理,如何编写一个插件
Mybatis的插件机制基于JDK动态代理实现,主要通过拦截核心接口方法来改变或增强框架的默认行为。具体原理如下:
-
拦截器接口定义: MyBatis提供了
Interceptor
接口,插件需要实现这个接口,其中包含三个方法:intercept(Invocation invocation)
:这是拦截的核心方法,当目标方法被调用时,会先执行这个方法。plugin(Object target)
:用于为目标对象生成一个代理对象,即创建一个实现了相同接口的代理类实例,从而能够在方法调用前后插入自定义逻辑。setProperties(Properties properties)
:允许设置插件的属性。
-
责任链模式: MyBatis使用责任链模式组织多个插件,形成插件链。当一个方法被调用时,它的请求会被传递给插件链中的每个插件,直到某个插件处理了该请求或者请求到达链尾未被处理。
-
动态代理: 插件实际生效是通过Java动态代理技术,对Executor、ParameterHandler、ResultSetHandler、StatementHandler等四大核心接口进行代理,在代理类的方法调用中插入插件的拦截逻辑。
-
方法拦截与匹配: 在
intercept()
方法中,插件可以根据需要判断是否要执行拦截操作,例如通过invocation.getMethod().getName()
获取被调用方法的名字,根据名字和参数类型等信息决定是否进行拦截,并执行相应的前置处理、后置处理或环绕处理。
如何编写一个Mybatis插件:
标签:插件,映射,sql,接口,SQL,Mybatis From: https://www.cnblogs.com/kzf-99/p/17967070