认识MyBatis核心组件及基本执行流程
MyBatis的核心组件分为四个部分:
SqlSessionFactoryBuilder(构造器):会根据配置或者代码来生成SqlSessionFactory,采用的是分步构建的Builder模式.
SqlSessionFactory(工厂接口):用它来生成SqlSession,使用的是工厂模式.
SqlSession(会话):一个既可以发送SQL执行返回结果,也可以获取Mapper的接口.一般我们会让其在业务逻辑代码中"消失".而使用的是MyBatis提供的SQL Mapper接口编程技术,它能提高代码的可读性和可维护性…
SQL Mapper(映射器):由一个Java接口和XML文件(或注解)构成,需要给出对应的SQL和映射规则.它负责发送SQL去执行,并返回结果.
SqlSessionFactory(工厂接口)
使用MyBatis首先是使用配置或者代码去生产SqlSessionFactory,而MyBatis提供了构造器SqlSessionFactoryBuilder(没有成员,只有一堆重载的builder方法,是类,只继承了Object),它提供了一个类Configuration作为引导,采用的是Builder模式.具体的分步则是在Configuration类里面完成的.
通过读取配置文件或者通过Java代码的形式去生成SqlSessionFactory.推荐使用XML形式,因为代码的形式在修改时会比较麻烦.当配置了XML或者提供代码后,MyBatis会读取配置文件,通过Configuration类对象构建整个MyBatis的上下文.SqlSessionFactory是一个接口,在MyBatis中它存在两个实现类:SqlSessionManager和DefaultSqlSessionFactory.一般而言是通过后者来实现的.而前者使用在多线程的环境中,它的具体实现依靠DefaultSqlSessionFactory.
每个基于MyBatis的应用都是以一个SqlSessionFactory的实例为中心的,而SqlSessionFactory唯一的作用就是生产MyBatis的核心接口对象SqlSession.所以他的责任是唯一的.我们往往会采用单例模式处理它.
MyBatis中的XML分为两类:
基础配置文件,通常只有一个,主要是配置一些最基本的上下文参数和运行环境;
映射文件,它可以配置映射关系,SQL,参数等信息.
基础配置文件中可以配置:
SqlSession
SqlSession是MyBatis的核心接口,它有两个实现类:
DefaultSqlSession:单线程使用,
SqlSessionManager:多线程使用
SqlSession类似于一个JDBC中的Connection对象,代表一个连接资源的启用.SqlSession的作用有3个:
获取Mapper接口.
发送SQL给数据库.
控制数据库事务.
SqlSession只是一个门面接口,真正干活的是Executor.
SqlSession获取Mapper接口和发送SQL的功能需要先实现映射器的功能.
SQL Mapper(映射器)
映射器是MyBatis中最重要,最复杂的组件,由一个接口和对应的XML文件(或注解)组成.
映射器可以配置以下内容:
描述映射规则.
提供SQL语句,并可以配置SQL参数类型,返回类型,缓存刷新等信息.
配置缓存.
提供动态SQL.
映射器的主要作用就是将SQL查询到的结果映射为一个POJO,或者将POJO的数据插入到数据库中,并定义一些关于缓存等的重要内容.MyBatis运用了动态代理技术为接口生成一个代理对象,代理对象会去处理相关的逻辑.
用XML方式创建映射器(推荐):
<?xml version="1.0" encoding="UTF-8"?> SELECT id,role_name as roleName,note FROM role WHERE id =#{id} MyBatis在默认情况下提供自动映射,只要SQL返回的列名能和POJO对应起来即可.注解实现映射器:
这种方式只需要一个接口就可以通过注解来诸如SQL:
package com.mybatis.mapper;
import org.apache.ibatis.annotations.Select;
import com.mybatis.po.Role;
public interface RoleMapper2 {
@Select(“select id,role_name as roleName,note from t_role where id=#{id}”)
public Role getRole(Long id);
}
如果注解和XML同时定义时,XML将会覆盖掉注解方式,推荐使用的是XML方式定义映射器.
使用注解的方式,当SQL语句比较复杂时,会降低代码的可读性,不利于日后的维护和修改.
XML可以相互引入,而注解不可以.
两种发送SQL的方式:
用SqlSession发送SQL
用Mapper接口发送SQL
推荐使用Mapper接口的方式,理由有:
使用Mapper接口编程可以消除SqlSession带来的功能性代码,提高可读性.
使用Mapper接口的方式,IDE会提示错误和校验,而使用SqlSession的方式只有在运行中才能知道是否会产生错误.
生命周期
根据每一个组件的作用去确定其生命周期
SqlSessionFactoryBuilder的作用在于创建SqlSessionFactory,创建成功后,就失去了作用,所以它只能存在于创建SqlSessionFactory的方法中,而不要让其长期存在.
SqlSessionFactory可以被认为是一个数据库连接池,它的作用是创建SqlSession接口对象.因为MyBatis的本质就是Java对数据库的操作,所以SqlSessionFactory的生命周期存在于整个MyBatis的应用中.所以一旦创建了SqlSessionFactory,就要长期保存他,直至不再使用MyBatis引用.
如果存在多个数据库连接池会导致数据库连接资源被消耗光,出现系统宕机等情况,所以一般希望SqlSessionFactory作为一个单例,在应用中被共享.
SqlSession相当于一个数据库连接对象,它应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让他归还给SqlSessionFactory.
Mapper是一个接口,由SqlSession所创建,它的最大生命周期至多和SqlSession保持一致,应该小于等于SqlSession的生命周期.Mapper代表的是一个请求中的业务处理,所以它应该在一个请求中,一旦处理完了相关的业务,就应该废弃它.
MyBatis执行流程:
创建一个SqlSessionFactoryBuilder对象,调用它的duilder方法
该方法会创建XMLConfigBuilder对象读取并解析MyBatis的全局配置文件,将配置信息封装为Environment对象存储到Configuration对象中,根据配置信息创建SqlSessionFactory对象.
XMLMapperBuilder读取并解析映射文件创建MappedStatement对象,将此对象存储在Configuration对象中.
SqlSessionFactory是个接口,默认会使用DefaultSqlSessionFactory对象.
使用DefaultSqlSessionFactory对象的openSession方法
该方法会返回一个SqlSession,SqlSession是个接口,默认会返回DefaultSqlSession对象.
每个DefaultSqlSession中有一个Executor成员,Executor接口有四个实现类:
如果使用getMapper方法,会使用动态代理返回一个SqlSession对应的代理对象
Executor会使用StatementHandler来执行SQL语句,而SQL语句对应的是MappedStatement,因此还需将MappedStatement对象传给StatementHandler对象.
执行过程中需要使用ParameterHandler来获取参数,用TypeHandler来处理java数据类型和数据表数据类型之间的映射和转换.
而用ResultSetHandler来处理结果集,期间又会使用到TypeHandler来处理java数据类型和数据表数据类型之间的映射和转换.
以上就是MyBatis的基本执行流程.
MyBatis的一级缓存及二级缓存
MyBatis的一级缓存是SqlSession级缓存
每个SqlSession使用各自的缓存.
一级缓存不需要POJO对象可序列化
如果不进行commit,是不会有一级缓存的.
一级缓存默认使用PerpetualCache缓存.
MyBatis的二级缓存是SqlSessionFactory级缓存
二级缓存可在多个SqlSession之间共享缓存,因此缓存需要保证线程安全.
二级缓存要求POJO对象可序列化.
二级缓存默认使用SynchronizedCache缓存.
缓存基本执行流程:
执行SQL时首先到缓存中找,如果不存在,访问数据库执行SQL,将查询到的结果放入缓存并将结果返回,如果缓存中有,直接从缓存中取,不访问数据库.期间进行增删改操作会刷新缓存.