欢迎关注WX公众号:“程序猿补课班”,分享Java相关技术知识,学习经验,面试经验等。小伙伴快来补课吧!
正文开始
1.#{}和${}的区别?
#是占位符,会对SQL进行预编译,相当于?;
$是做sql拼接,有SQL注入的隐患
两者都支持@param注解,指定参数名称,获取参数值.
推荐这种方式一般做参数传递,都会使用#{}
如果不是做预编译,而是做拼接sql,会使用${}, 例如表名称的变化,
2.Mapper 接口如何传递多个参数?
方式一、接口中传多个参数,在 xml 中使用 #{param0}、#{param1}…
方式二、使用 @param 注解指定名称,在 xml 中使用 #{名称}
方式三、多个参数封装到 Java bean 中
方式四、多个参数指定 key,put 到 Map 中
3.Mybatis 是如何将sql执行结果封装为目标对象并返回的?都有哪些映射形式?
第一种是使用标签,逐一定义列名和对象属性名之间的映射关系。
第二种是使用 sql 列的别名功能,将列别名书写为对象属性名,比如 T_NAME AS NAME,对象属性名一般是 name,小写,但是列名不区分大小写,Mybatis 会忽略列名大小写,智能找到与之对应对象属性名,你甚至可以写成T_NAME AS NaMe,Mybatis 一样可以正常工作。
有了列名与属性名的映射关系后,Mybatis 通过反射创建对象,同时使用反射给对象的属性逐一赋值并返回,那些找不到映射关系的属性,是无法完成赋值的。
4.Mybatis是如何进行分页的?分页插件的原理是什么?
Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。
分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。
5.Mybatis 是否支持延迟加载?如果支持,它的实现原理是什么?
1、 Mybatis 仅支持 association 关联对象和 collection 关联集合对象的延迟加载,association指的就是一对一,collection 指的就是一对多查询。在 Mybatis 配置文件中,可以配置是否启用延迟加载 lazyLoadingEnabled=true|false。
2、 它的原理是,使用 CGLIB 创建目标对象的代理对象,当调用目标方法时,进入拦截器方法,比如调用 a.getB().getName(),拦截器 invoke()方法发现 a.getB()是 null 值,那么就会单独发送事先保存好的查询关联 B 对象的 sql,把 B 查询上来,然后调用 a.setB(b),于是 a 的对象 b 属性就有值了,接着完成 a.getB().getName()方法的调用。这就是延迟加载的基本原理。
6.Mybatis 动态 sql 是做什么的?都有哪些动态 sql?能简述一下动态 sql 的执行原理不?
a、Mybatis 动态 sql 可以让我们在 Xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能。
b、Mybatis提供了9种动态sql标签:trim|where|set|foreach|if|choose|when|otherwise|bind。
c、其执行原理为,使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。
7.使用 MyBatis 的 mapper 接口调用时有哪些要求?
1、Mapper 接口方法名和 mapper.xml 中定义的每个 sql 的 id 相同;
2、Mapper 接口方法的输入参数类型和 mapper.xml 中定义的每个 sql 的
parameterType 的类型相同;
3、Mapper 接口方法的输出参数类型和 mapper.xml 中定义的每个 sql 的
resultType 的类型相同;
4、Mapper.xml 文件中的 namespace 即是 mapper 接口的类路径。
8.Mybatis 一级缓存和二级缓存了解吗?
一级缓存
Mybatis的一级缓存是指SQLSession,一级缓存的作用域是SQlSession, Mabits默认开启一级缓存。 在同一个SqlSession中,执行相同的SQL查询时;第一次会去查询数据库,并写在缓存中,第二次会直接从缓存中取。
当执行SQL时候两次查询中间发生了增删改的操作,则SQLSession的缓存会被清空。 每次查询会先去缓存中找,如果找不到,再去数据库查询,然后把结果写到缓存中。Mybatis的内部缓存使用一个HashMap,key为hashcode+statementId+sql语句。Value为查询出来的结果集映射成的java对象。SqlSession执行insert、update、delete等操作commit后会清空该SQLSession缓存。
二级缓存
二级缓存是mapper级别的,Mybatis默认是没有开启二级缓存的。
第一次调用mapper下的SQL去查询用户的信息,查询到的信息会存放该mapper对应的二级缓存区域。 第二次调用namespace下的mapper映射文件中,相同的sql去查询用户信息,会去对应的二级缓存内取结果。
9.Mybatis的Xml映射文件中,不同的Xml映射文件,id是否可以重复?
不同的 Xml 映射文件,如果配置了 namespace,那么 id 可以重复;
如果没有配置 namespace,那么 id 不能重复;原因就是 namespace+id 是作为 Map<String, MapperStatement>的 key使用的,如果没有 namespace,就剩下 id,那么,id 重复会导致数据互相覆盖。有了 namespace,自然 id 就可以重复,namespace 不同,namespace+id 自然也就不同。
10.mybatis如何获取生成的主键
自增主键
第一种方式是使用useGeneratedKeys + keyProperty组合的方式,其中userGeneratedKeys代表是告诉mybatis要使用自增生成的主键,keyProperty是告诉mybatis主键字段是哪个,如下:
<insert id="insert" parameterType="Person" userGeneratedKeys="true" keyProperty="id">
INSERT INTO person(name, pswd) VALUE (#{name}, #{pswd})
</insert>
对于不支持自动生成主键的数据库Oracle、DB2等,可以用元素selectKey 回写当前插入数据主键值到输入类中(同时生成一个自定义的随机主键),注意这里order="BEFORE",因为要在执行数据操作之前生成id值。
<insert id="insertTest" useGeneratedKeys="true" keyProperty="id" parameterType="com.kq.domain.IdentityTest">
<selectKey keyProperty="id" resultType="String" order="BEFORE">
SELECT REPLACE(UUID(),'-','')
</selectKey>
insert into identity_test(name) values(#{name,jdbcType=VARCHAR})
</insert>
如有错漏之处,敬请指正