参考书籍《深入浅出MyBatis技术原理与实战》
MyBatis
基本构成
SqlSessionFactoryBuilder(构造器):它会根据配置信息或者代码来生成SqlSessionFactory(工厂接口)
SqlSessionFactory:依靠工厂接口来创建SqlSession(回话)
SqlSession:是一个既可以发送SQL去执行并返回结果,也可以获取一个Mapper接口
SQL Mapper:他是一个由Java接口和XML文件(或者注解)构成,需要给出对应的SQL和映射规则,他负责发送SQL去执行,并返回结果。
String resource = "mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
//建立Sqlsession
sqlSession = sqlSessionFactory.openSession();
SqlSessionFactory
每个MyBatis的应用都是以SqlSessionFactory的实例为中心的。SqlSessionFactory的实例可以通过SqlSessionFactoryBuilder获得。SqlSessionFactory是一个工厂接口而不是实现类,他的任务是创建SqlSession。SqlSession类似于JDBC的Connection对象。SqlSessionFactory有两种方式创建,一种是通过XML配置的方式,另一种是代码的方式,一般使用XML配置,因为可以避免硬编码同时也方便配置人员的修改。
SqlSessionFactory的实现类有两个,DefaultSqlSessionFactory和SqlSessionManager。
SqlSession
SqlSession是一个接口类,真正执行的是Executor接口。在MyBatis中,SqlSession接口的实现类有两个,DefaultSqlSession和SqlSessionManager。SqlSession类似于JDBC的Connection对象。
SqlSession的用途主要有两种:
获取映射器,让映射器通过命名空间和方法名称找到对应的SQL,发送给数据库执行后返回结果。
sqlSession.selectOne("com.wy.bean.StudentMapper.selectStudentBySname",s);
直接通过命名信息去执行SQL并返回结果。在SqlSession可以通过update,insert,select等方法,带上SQL的id来操作在XML中配置好的SQL;同时支持事务,通过commit,rollback方法提交或者回滚事务。
Student s = new Student(); s.setSname("沪"); s.setSpwd("666"); s.setCid(1); sqlSession.insert("com.wy.bean.StudentMapper.insertStudent", s);
映射器Mapper
映射器由Java接口和XML文件(或注解)共同组成,作用有:
定义参数类型
描述缓存
描述SQL语句
定义查询结果和POJO(一个Java对象类)的映射关系
一个映射器有两种实现方式; 一是通过XML文件方式实现(xxxMapper.xml),来生成Mapper。另一种是通过代码实现(一个接口,在方法上使用注解实现特定的SQL语句)。
XML实现
<!-- 根据名字查找学生 -->
<!-- 注意:在mybatis-config.xml没有配置类别名的时候需要写上类的全路径 com.wy.bean.Student-->
<select id="selectStudentBySname" resultType="Student" parameterType="Student">
select * from student where sname = #{sname}
</select>
代码实现
@Mapper
public interface GoodsDao {
@Select("select xxx ...")
public List<GoodsVo> listGoodsVo();
一个接口怎么就能查询出我们想要的结果呢?其实用到了Java的动态代理去实现。MyBatis会为这个接口生成代理类对象,代理对象会根据“接口全路径+方法名”去匹配,找到对应的XML文件(或注解)去完成相应的SQL并返回我们需要的结果。
生命周期
SqlSessionFactoryBuilder
SqlSessionFactoryBuilder是利用XML或者Java代码获得资源来构建SqlSessionFactory的,通过它可以构建多个SqlSessionFactory。SqlSessionFactoryBuilder的作用就是一个构造器,一旦创建了SqlSessionFactory,它的作用就完结了,失去了存在的意义,因此我们就可以对它进行回收。所以SqlSessionFactoryBuilder的生命周期只存在方法的局部,作用就是创建SqlSessionFactory。
SqlSessionFactory
SqlSessionFactory的作用是创建SqlSession,而SqlSession就是一个会话,相当于JDBC中的Connection对象。每次应用程序访问数据库,我们就要通过SqlSessionFactory创建SqlSession,所以SqlSessionFactory在MyBatis应用的整个生命周期中。如果我们多次创建SqlSessionFactory,则SqlSessionFactory会打开更多的数据库连接,导致连接资源很快就会被耗尽,因此我们采用单例模式,使得每一个数据库只对应一个SqlSessionFactory,管理好数据库资源的分配,避免过多的连接被消耗。
SqlSession
SqlSession是一个会话,相当于JDBC的一个Connection对象,它的生命周期是在请求数据库处理事务的过程中。它存活于一个应用的请求和操作,可以执行多条SQL,保证事务的一致性。它是一个线程不安全的对象,此外,每次创建SqlSession都必须及时关闭它,因为长期存在会使数据库连接池的活动资源减少,影响系统性能。
Mapper(映射器)
Mapper是一个接口,没有任何的实现类,它的作用是发送SQL,然后返回我们需要的结果,或者执行SQL从而修改数据库数据。它就如同JDBC中的一条SQL语句的执行。因此它是在一个SqlSession事务方法之内,是一个方法级别的东西。
缓存cache
目前流行的缓存服务器有MongoDB,Redis,Ehcache。缓存是在计算机内存中保存数据,在读取时无需在从磁盘读入,因此具备快速读取和使用的特点。
系统缓存
一级缓存
MyBatis默认缓存只开启一级缓存(一级缓存只是相对于同一个SqlSession而言)。所以在参数和SQL完全一样的情况下,我们使用同一个SqlSession对象调用同一个Mapper的方法,往往只执行一次SQL,因为在使用SqlSession第一次查询后,MyBatis会将结果放在缓存中。
二级缓存
因为SqlSession是相互隔离的,如果我们需要不同的SqlSession都具有相同的缓存,因此我们需要配置二级缓存,使得缓存在SqlSessionFactory层面上能够提供给各个SqlSession对象共享。
二级缓存不是默认开启的,因此我们需要进行配置,实现二级缓存MyBatis要求返回POJO(POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBeans)
必须的可序列化的,因此需要实现Serializable接口。
开启缓存只需要在配置文件增加以下语句即可
<cache/>
缓存默认是使用最近最少使用算法来回收的。还有先进先出,软引用等。
自定义缓存
可以使用Redis缓存。(没用过…)
MyBatis解析和运行原理
涉及的技术,反射,动态代理。因为Mapper是一个接口,因此使用JDK动态代理可以很好的实现。
构建SqlSessionFactory过程
SqlSessionFactory是MyBatis的核心类之一,功能是创建核心接口SqlSession。我们采用构造模式创建SqlSessionFactory,可以通过SqlSessionFactoryBuilder去构建,构建分为两步。
第一步通过XMLConfigBuilder解析配置的XML文件,读取配置参数,并将读取的数据存入Configuration类中,MyBatis几乎所有 配置都是存在这里。
第二步,使用Configuration对象创建SqlSessionFactory
构建SqlSessionFactory过程
SqlSessionFactory是MyBatis的核心类之一,功能是创建核心接口SqlSession。我们采用构造模式创建SqlSessionFactory,可以通过SqlSessionFactoryBuilder去构建,构建分为两步。
1. 第一步通过XMLConfigBuilder解析配置的XML文件,读取配置参数,并将读取的数据存入Configuration类中,MyBatis几乎所有 配置都是存在这里。
2. 第二步,使用Configuration对象创建SqlSessionFactory。SqlSessionFactory是一个接口,MyBatis为我们提供了一个默认的SqlSessionFactory实现类,DefaultSqlSessionFactory。SqlSessionManager也是一个实现类。
构建Configuration
在SqlSessionFactory构建中,Configuration是最重要的,作用如下:
读取配置文件,包括基础配置的XML文件和映射器的XML文件
初始化基础配置,比如MyBatis的别名等,一些重要的类对象,比如,插件,映射器等
提供单例,为后面创建SessionFactory服务并提供配置的参数
执行一些重要的对象方法,初始化配置信息
映射器的内部组成
一般而言,一个映射器由三个部分组成
MappedStatement,它保存映射器的一个节点(select,insert,update,delete)。包括许多我们配置的SQL,resultMap等配置内容。
SqlSource,是一个接口,它是提供BoundSql对象的地方,它是MappedStatement的一个属性。主要作用是根据参数和其他规则组装SQL(比如动态SQL)
BoundSql,是建立SQL和参数的地方。它有三个常用的属性,SQL(我们在映射器里面的一条SQL),parameterObject,parameterMapping(它是一个List)。
构建SqlSessionFactoy
有了Configuration对象构建SqlSessionFactoy就很简单
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
MyBatis会根据Configuration的配置读取配置信息,构建SqlSessionFactoy对象。
SqlSession运行过程
SqlSession是一个接口,提供了增删改查的方法。实现它的功能是通过动态代理,让这个接口跑起来。
SqlSession下的四大对象
映射器其实就是一个动态代理对象。Mapper执行的过程是通过Executor,StatementHandler,ParameterHandler和ResultHandler来完成数据库操作和结构返回的。
Executor代表执行器,由它来调度StatementHandler,ParameterHandler和ResultHandler等来执行对应的SQL
StatementHandler的作用是使用数据库的Statement(PrepareStatement)执行操作,它是四大对象的核心,起到承上启下的作用
ParameterHandler用于SQL对参数的处理
ResultHandler是进行最后数据集(ResultSet)的封装返回处理的
执行器Executor
执行器Executor是真正执行Java和数据库交互的东西。MyBatis中三种执行器。
SIMPLE,简易执行器,默认的执行器
REUSE,是一种执行器重用预处理语句
BATCH,执行器重用语句和批量更新,它是针对批量专用的执行器
数据库会话器StatementHandler
数据库会话器StatementHandler是专门处理数据库会话的。
参数处理器ParameterHandler
MyBatis通过参数处理器ParameterHandler对预编译语句进行参数设置。作用是完成对预编译参数的设置。
结果处理器ResultHandler
ResultHandler是进行最后数据集(ResultSet)的封装返回处理的