Mybatis面试合集
目录
一:什么是mybatis
二:Mybaits的优缺点
三:#{} 和 ${}的区别
四:mybatis是什么时候把#{}替换成 ? 的
五:Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
六:Mybatis的一级缓存和二级缓存
七:动态sql
八:模糊查询like语句该怎么写?
九:mybatis如何去自定义主键策略
1、selectKey 标签作用1:获取自增主键
2、selectKey 标签作用2:自定义主键的生成方式
3、selectKey 标签属性介绍
4、selectKey 标签与 useGeneratedKeys、keyProperty 属性
一:什么是mybatis
(1)Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,加载驱动、创建连接、创建statement等繁杂的过程,开发者开发时只需要关注如何编写SQL语句,可以严格控制sql执行性能,灵活度高。
(2)作为一个半ORM框架,MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
(3)通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。
(4)由于MyBatis专注于SQL本身,灵活度高,所以比较适合对性能的要求很高,或者需求变化较多的项目,如互联网项目。
二:Mybaits的优缺点
(1)优点:
① 与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
② 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
③ 很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。
④ 能够与Spring很好的集成;
⑤ 提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
(2)缺点:
① SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
② SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
三:#{} 和 ${}的区别
${}是字符串替换,#{}是预处理;使用#{}可以有效的防止SQL注入,提高系统安全性。
Mybatis在处理${}时,就是把${}直接替换成变量的值。而Mybatis在处理#{}时,会对sql语句进行预处理,将sql中的#{}替换为?号,调用PreparedStatement的set方法来赋值;
- #{}:编译好SQL后语句再去取值
- ${}:取值以后再去编译SQL语句
四:mybatis是什么时候把#{}替换成 ? 的
1、流程
- #{}:动态解析 -> 预编译 -> 执行
- ${}:动态解析 -> 编译 -> 执行
2、案例
根据用户名name查询用户表user数据,如果 name 的值为 zhangsan
#{}
select * from user where name = #{name};
${}
select * from user where name = ${name};
(2)(预)编译中的处理
#{}:在预处理时,会把参数用一个占位符" ?" 代替,变成以下SQL
select * from user where name = ?;
${}:只是简单的字符串替换,在动态解析时变成以下SQL
select * from user where name = 'zhangsan';
当然了,最后的解析结果是一样的,都是
select * from user where name = 'zhangsan';
五:Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
不同的Xml映射文件,如果配置了namespace,那么id可以重复;如果没有配置namespace,那么id不能重复;原因就是namespace+id是作为Map的key使用的,如果没有namespace,就剩下id,那么,id重复会导致数据互相覆盖。有了namespace,自然id就可以重复,namespace不同,namespace+id自然也就不同。
备注:在旧版本的Mybatis中,namespace是可选的,不过新版本的namespace已经是必填项了。
六:Mybatis的一级缓存和二级缓存
区别:
- 一级缓存的作用域是一个sqlsession内;
- 二级缓存作用域是针对mapper进行缓存;
一级缓存:
在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用一个Mapper方法,往往只执行一次SQL,因为使用SelSession第一次查询后,MyBatis会将其放在缓存中,以后再查询的时候,如果没有声明需要刷新,并且缓存没有超时的情况下,SqlSession都会取出当前缓存的数据,而不会再次发送SQL到数据库。
二级缓存:
二级缓存的作用域是mapper的同一个namespace。二级缓存是mapper级别的缓存。使用二级缓存时,多个SqlSession使用同一个Mapper的sql语句去操作数据库,得到的数据会存在二级缓存区域,它同样是使用HashMap进行数据存储。相比一级缓存SqlSession,二级缓存的范围更大,多个Sqlsession可以共用二级缓存,二级缓存是跨SqlSession的。
七:动态sql
Mybatis动态sql可以在Xml映射文件内,以标签的形式编写动态sql,执行原理是根据表达式的值 完成逻辑判断 并动态拼接sql的功能。Mybatis提供了9种动态sql标签:trim | where | set | foreach | if | choose | when | otherwise | bind。
标签使用例子
八:模糊查询like语句该怎么写?
第1种:在Java代码中添加sql通配符。
string wildcardname = “%smi%”;
list<name> names = mapper.selectlike(wildcardname);
<select id=”selectlike”>
select * from foo where bar like #{value}
</select>
第2种:在sql语句中拼接通配符,会引起sql注入
string wildcardname = “smi”;
list<name> names = mapper.selectlike(wildcardname);
<select id=”selectlike”>
select * from foo where bar like "%"${value}"%"
九:mybatis如何去自定义主键策略
有时候新增一条数据不仅仅要知道是否插入成功,因为后面的逻辑可能还需要这条新增数据的主键,这时候可以使用selectKey 标签获取自增主键,从而避免再次查询数据库。另外,有些业务需要自定义数据表的主键,这个时候也可以使用selectKey 标签来实现,它可以随意的设置生成主键的方式。
1、selectKey 标签作用1:获取自增主键
通常情况下,新增一条数据信息,其主键ID是数据库自动生成的,一般采用自增的形式。selectKey 标签可以获取这个生成的主键。如下所示:
<insert id="addUser" parameterType="cn.mybatis.entity.User">
<selectKey resultType="java.lang.Integer" order="AFTER" keyProperty="id">
select LAST_INSERT_ID()
</selectKey>
insert into t_user(name,sex,phone) values (#{name},#{sex},#{phone})
</insert>
UserDao.add(user);
Integer userId = user.getId();
System.out.println("新增用户的id为:" + userId);
selectKey 标签的作用:首先在数据库插入user对象,然后执行 select LAST_INSERT_ID()
获取数据库里自动生成的主键,最后赋值给user对象的id属性。
2、selectKey 标签作用2:自定义主键的生成方式
除了自动生成主键以外,有些业务需要自定义数据表的主键,这个时候也可以使用selectKey 标签来实现,如下所示:
<insert id="addUser" parameterType="cn.mybatis.entity.User">
<selectKey resultType="string" order="BEFORE" keyProperty="id">
select uuid()
</selectKey>
insert into t_user(id,name,sex,phone) values (#{id},#{name},#{sex},#{phone})
</insert>
3、selectKey 标签属性介绍
- keyProperty:对应Java实体类中充当主键的属性名,跟数据库的主键对应;
- order:取值 AFTER 或者 BEFORE。如上例子所述,AFTER 表示在insert执行之后执行
SELECT LAST_INSERT_ID()
,多用获取自增主键;BEFORE 表示在insert执行之前执行select uuid(),适合那种主键不是自增的情况,实现自定义主键。 - resultType:主键类型
4、selectKey 标签与 useGeneratedKeys、keyProperty 属性
其实,获取自增主键的方式除了使用selectKey 标签以外,还可以使用useGeneratedKeys、keyProperty 属性,可以参考:MyBatis keyProperty 属性介绍,相对来说,后者更简洁。