[Interview]Java 面试宝典系列之 MyBatis
Posted Spring-_-Bear
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Interview]Java 面试宝典系列之 MyBatis相关的知识,希望对你有一定的参考价值。
文章目录
1. 谈谈 MyBatis 和 JPA 的区别
- ORM(
Object-Relationl Mapping
)映射不同:- MyBatis 是半自动的 ORM 框架,提供数据库与结果集的映射
- JPA(
Java Persistence API
)(默认采用Hibernate
实现)是全自动的 ORM 框架,提供对象与数据库的映射
- 可移植性不同:
- JPA 通过它强大的映射结构和
HQL
语言,大大降低了对象与数据库的耦合性 - MyBatis 由于需要写 SQL,因此与数据库的耦合性直接取决于 SQL 的写法,如果 SQL 不具备通用性而用了很多数据库的特性 SQL 的话,移植性就会降低很多,移植时成本很高
- JPA 通过它强大的映射结构和
- 日志系统的完整性不同:
- JPA 日志系统非常健全、涉及广泛,包括:SQL 记录、关系异常、优化警告、缓存提示、脏数据警告等
- MyBatis 除了基本的记录功能外,日志功能薄弱很多
- SQL 优化上的区别:
- 由于 Mybatis 的 SQL 都是写在 XML 里,因此优化 SQL 比 Hibernate 方便很多
- Hibernate 的 SQL 很多都是自动生成的,无法直接维护 SQL。虽有 HQL,但功能还是不及 SQL 强大,见到报表等复杂需求时 HQL 就无能为力,也就是说 HQL 是有局限的。Hibernate 虽然也支持原生 SQL,但开发模式上却与 ORM 不同,需要转换思维,因此使用上不是很方便。总之写 SQL 的灵活度上 Hibernate 不及 Mybatis
2. MyBatis 输入输出支持的类型有哪些?
MyBatis 支持多种输入输出类型,包括:
- 简单的基本数据类型,如整数、小数、字符串等
- 集合类型,如 Map 等
- 自定义的 JavaBean
其中,简单的类型,其数值直接映射到参数上。对于 Map 或 JavaBean 则将其属性按照名称映射到参数上。
3. MyBatis 里如何实现一对多关联查询?
一对多映射有两种配置方式,都是使用 collection
标签实现的。在此之前,为了能够存储一对多的数据,需要在主表对应的实体类中增加集合属性,用于封装子表对应的实体类
嵌套查询:
- 通过 select 标签定义查询主表的 SQL,返回结果通过 reusltMap 进行映射
- 在 resultMap 中,除了映射主表属性,还要通过 collection 标签映射子表属性,该标签需包含如下内容:
- 通过 property 属性指定子表属性名
- 通过 javaType 属性指定封装子表属性的集合类型
- 通过 ofType 属性指定子表的实体类型
- 通过 select 属性指定查询子表所依赖的 SQL,这个 SQL 需单独定义,内部包含查询子表的语句
嵌套结果:
- 通过 select 标签定义关联查询主表和子表的 SQL,返回结果通过 resultMap 进行映射
- 在 resultMap 中,除了映射主表属性,还要通过 collection 标签映射子表属性,该标签需包含如下内容:
- 通过 property 属性指定子表属性名
- 通过 ofType 属性指定子表的实体类型
- 通过 result 子标签定义子表字段和属性的映射关系
<!-- 方式一:多表联查为集合中的 bean 赋值 -->
<resultMap id="empInDeptResultMap" type="Dept">
<id property="did" column="did"/>
<result property="deptName" column="dept_name"/>
<!-- ofType 属性设置集合存储的 bean 类型 -->
<collection property="empList" ofType="Emp">
<id property="eid" column="eid"/>
<result property="empName" column="emp_name"/>
<result property="sex" column="sex"/>
<result property="age" column="age"/>
<result property="email" column="email"/>
</collection>
</resultMap>
<!-- Dept getEmpInDeptByDid(@Param("did")Integer did); -->
<select id="getEmpInDeptByDid" resultMap="empInDeptResultMap">
select * from t_dept left join t_emp on t_dept.did = t_emp.did where t_dept.did = #did
</select>
4. MyBatis 中的 $ 和 # 有什么区别?
- 使用 # 设置参数时,MyBatis 会创建预编译的 SQL 语句,然后在执行 SQL 时 MyBatis 会为预编译 SQL 中的占位符(?)赋值。预编译的 SQL 语句执行效率高,并且可以防止 SQL 注入
- 使用 $ 设置参数时,MyBatis 只是创建普通的 SQL 语句,然后在执行 SQL 语句时MyBatis将参数直接拼入到 SQL 里。这种方式在效率、安全性上均不如前者,但是可以解决一些特殊情况下的问题。例如,在一些动态表格(根据不同的条件产生不同的动态列)中,我们要传递 SQL 的列名,根据某些列进行排序,或者传递列名给 SQL 都是比较常见的场景,这就无法使用预编译的方式了
5. 既然 $ 不安全,为什么还需要 $,什么时候会用到它?
它可以解决一些特殊情况下的问题。例如,在一些动态表格(根据不同的条件产生不同的动态列)中,我们要传递 SQL 的列名,根据某些列进行排序,或者传递列名给 SQL 都是比较常见的场景,这就无法使用预编译的方式了。
- 动态表名查询
- 动态列名查询
6. MyBatis 的 xml 文件和 Mapper 接口是怎么绑定的?
是通过 xml 文件中,<mapper>
根标签的 namespace
属性进行绑定的,即 namespace 属性的值需要配置成接口的全限定名称,MyBatis 内部就会通过这个值将这个接口与这个 xml 关联起来。
7. MyBatis 分页和自己写的分页哪个效率高?
自己写的分页效率高。在 MyBatis 中,我们可以通过分页插件实现分页,也可以通过分页 SQL 自己实现分页。其中,分页插件的原理是,拦截查询 SQL,在这个 SQL 基础上自动为其添加 limit 分页条件。它会大大的提高开发的效率,但是无法对分页语句做出有针对性的优化,比如分页偏移量很大的情况,而这些在自己写的分页 SQL 里却是可以灵活实现的。
8. 了解 MyBatis 缓存机制吗?
MyBatis的缓存分为一级缓存和二级缓存。
-
一级缓存:一级缓存也叫本地缓存,它默认会启用,并且不能关闭。一级缓存存在于
SqlSession
的生命周期中,即它是 SqlSession 级别的缓存。在同一个 SqlSession 中查询时,MyBatis 会把执行的方法和参数通过算法生成缓存的键值,将键值和查询结果存入一个 Map对象中。如果同一个 SqlSession 中执行的方法和参数完全一致,那么通过算法会生成相同的键值,当 Map 缓存对象中己经存在该键值时,则会返回缓存中的对象。 -
二级缓存:二级缓存是
SqlSessionFactory
级别的,通过同一个 SqlSessionFactory 创建的 SqlSession 查询的结果才会被缓存,缓存的数据只能通过同一个 SqlSessionFactory 创建的 SqlSession 才能访问。两次查询之间执行了任意的增删改,会使一级、二级缓存同时失效。二级缓存开启的四个条件:- 在核心配置文件中配置全局属性
cacheEnabled="true"
,默认为 true - 在对应的 mapper 映射文件中设置标签
<cache/>
- 查询的数据转换成的 JavaBean 类必须实现
Serilizable
序列化接口 - 只有在 SqlSession 关闭或提交之后二级缓存才会生效
二级缓存具有如下效果:
- 映射语句文件中的所有 SELECT 语句将会被缓存
- 映射语句文件中的所有 INSERT 、UPDATE 、DELETE 语句会刷新缓存
- 缓存会使用 Least Recently Used ( LRU ,最近最少使用的)算法来收回
- 根据时间表(如 no Flush Interval ,没有刷新间隔),缓存不会以任何时间顺序来刷新
- 缓存会存储集合或对象(无论查询方法返回什么类型的值)的 1024 个引用
- 缓存会被视为 read/write(可读/可写)的,意味着对象检索不是共享的,而且可以安全地被调用者修改,而不干扰其他调用者或线程所做的潜在修改
- 在核心配置文件中配置全局属性
以上是关于[Interview]Java 面试宝典系列之 MyBatis的主要内容,如果未能解决你的问题,请参考以下文章
[Interview]Java 面试宝典系列之 Spring Boot
[Interview]Java 面试宝典系列之 Java 多线程
[Interview]Java 面试宝典系列之 MyBatis
[Interview]Java 面试宝典系列之 Java 集合类