Mybatis是什么
- Mybatis是一个半ORM(对象关系映射)框架,它内部封装了JDBC,加载驱动、创建连接、创建statement等繁杂的过程,开发者开发时只需要关注如何编写SQL语句,可以严格控制sql执行性能,灵活度高。
- 作为一个半ORM框架,MyBatis 可以使用 XML 或注解来配置和映射原生信息,将 POJO映射成数据库中的记录,避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集。
- 通过xml 文件或注解的方式将要执行的各种 statement 配置起来,并通过java对象和 statement中sql的动态参数进行映射生成最终执行的sql语句,最后由mybatis框架执行sql并将结果映射为java对象并返回。(从执行sql到返回result的过程)。
- 由于MyBatis专注于SQL本身,灵活度高,所以比较适合对性能的要求很高,或者需求变化较多的项目,如互联网项目。
Mybatis优缺点
优点
- 基于SQL语句编程,相当灵活,不会对应用程序或者数据库的现有设计造成任何影响,SQL写在XML里,解除sql与程序代码的耦合,便于统一管理;提供XML标签,支持编写动态SQL语句,并可重用。
- 与JDBC相比,减少了50%以上的代码量,消除了JDBC大量冗余的代码,不需要手动开关连接;
- 很好的与各种数据库兼容(因为MyBatis使用JDBC来连接数据库,所以只要JDBC支持的数据库MyBatis都支持)。
- 能够与Spring很好的集成;
- 提供映射标签,支持对象与数据库的ORM字段关系映射;提供对象关系映射标签,支持对象关系组件维护。
缺点
- SQL语句的编写工作量较大,尤其当字段多、关联表多时,对开发人员编写SQL语句的功底有一定要求。
- SQL语句依赖于数据库,导致数据库移植性差,不能随意更换数据库。
Mybatis与Hibernate有哪些不同?
- Mybatis不是完全的ORM框架,需要程序员自己编写Sql语句,灵活性高,适合对关系数据模型要求不高的软件开发。
- Mybatis无法做到是数据无关性,如果需要实现支持多种数据库的软件,则需要自定义多套sql映射文件;Hibernate对象/关系映射能力强,有较好的数据无关性。
#{}
与${}
的区别
${}
是变量占位符,可以用于标签属性值和sql内部,属于原样文本替换,可以替换任何内容。
select * from users order by ${orderCols}
#{}
是 sql 的参数占位符,MyBatis 会将 sql 中的#{}
替换为? 号,在 sql 执行前会使用 PreparedStatement 的参数设置方法,按序给 sql 的? 号占位符设置参数值,比如ps.setInt(0, parameterValue)
,#{item.name}
的取值方式为使用反射从参数对象中获取 item 对象的 name 属性值,相当于param.getItem().getName()
。
Mybatis执行流程
- 加载Mybatis配置文件: mybatis-config.xml加载运行环境和映射文件
- 构造会话工厂SqlSessionFactory
- 会话工厂创建SqlSession对象(包含执行SQL语句的所有方法)
- Executor操作数据库的接口,同时负责查询缓存的维护
- Executor接口的执行方法中有一个MappedStatement类型的参数,封装了映射信息
- 输入参数映射
- 输出结果映射
Mybatis是否支持延迟加载
Mybatis支持延迟加载,但默认没有开启
- 延迟加载意思是:需要用到数据时才进行加载,不需要用到数据就不加载数据
- Mybatis中支持一对一关联对象和一对多关联集合对象的延迟加载
- 在Mybatis配置文件中,可以配置是否采用延迟加载lazyLoadingEnabled=true|false
何为延迟加载
- 使用CGLIB创建目标对象的代理对象
- 当调用目标方法user.getOrderList()时,进入拦截器invoke方法,发现user.getOrderList()是null值,执行sql查询order列表
- 查询到order后,调用user.setOrderList(List orderList),利用set方法设置属性值,在继续查询目标方法,完成user.getOrderList()的方法调用。
Mybatis的一级、二级缓存
- 一级缓存:基于PerpetualCache的HashMap本地缓存,其作用域为Session。当Session进行Flush或者Close之后,该Session中所有的Cache就将清空,默认打开一级缓存。
- 二级缓存是基于namespace和mapper的作用域起作用,不依赖于SQL session,默认也是采用Perpetual,HashMap存储。需要单独开启。一个是在核心配置中改为True,一个是在mapper映射文件中添加’\cache’标识。
Mybatis的二级缓存什么时候回清理缓存中的数据
当某一个作用域(一级缓存Session/二级缓存Namespaces)进行了增删改操作后,默认该作用域下所有select中的缓存都将被删除。
Dao 接口的工作原理是什么?Dao 接口里的方法,参数不同时,方法能重载吗?
Dao
接口,即Mapper
接口,通常每个xml映射文件都会有一个Dao接口与之对应。接口的权限名就是映射文件中namespace
的值;接口的方法名即为MappedStatement
的id值;接口方法内的参数就是传递给sql的参数。Mapper
接口是没有实现类的,当调用接口方法时,将接口权限名+方法名拼接字符串作为key值,可以定位一个MappedStatement
。
举例:com.mybatis3.mappers. StudentDao.findStudentById
,可以唯一找到 namespace
为 com.mybatis3.mappers. StudentDao
下面 id = findStudentById
的 MappedStatement
。在 MyBatis 中,每一个 <select>
、 <insert>
、 <update>
、 <delete>
标签,都会被解析为一个 MappedStatement
对象。
Mybatis 的 Dao 接口可以有多个重载方法,但是多个接口对应的映射必须只有一个,否则启动会报错。
在Mapper中如何传递多个参数
-
若Dao层函数有多个参数,那么其对应的xml中,#{0}代表接收的是Dao层中的第一个参数,#{1}代表Dao中的第二个参数,以此类推。
-
使用@Param注解:在Dao层的参数中前加@Param注解,注解内的参数名为传递到Mapper中的参数名。
-
多个参数封装成Map,以HashMap的形式传递到Mapper中。
Mybatis动态sql是做什么的?都有哪些动态sql?能简述一下动态sql的执行原理吗?
MyBatis 动态 sql 可以让我们在 xml 映射文件内,以标签的形式编写动态 sql,完成逻辑判断和动态拼接 sql 的功能。其执行原理为,使用 OGNL 从 sql 参数对象中计算表达式的值,根据表达式的值动态拼接 sql,以此来完成动态 sql 的功能。
提供了9种动态sql标签
<if></if>
<where></where>(trim,set)
<choose></choose>(when, otherwise)
<foreach></foreach>
<bind/>