在使用Mybatis时,我们通常将其配置在Spring容器中,当Spring启动的时候会自动加载Mybatis的所有配置文件然后生成注入到Spring中的Bean,本文从实用的角度进行Mybatis源码解读,会关注以下一些方面:
- Mybatis都有哪些配置文件和配置项
- Mybatis初始化的源码流程;
- Mybatis初始化后,产生了哪些对象;
Mybatis初始化环境并且执行SQL语句的JAVA代码
先看一段初始化Mybatis环境并且执行SQL语句的Java代码:
package org.apache.ibatis.session;
import java.io.Reader;
import org.apache.ibatis.io.Resources;
public class MyTest {
public static void main(String[] args) throws Exception {
// 开始初始化
final String resource = "org/apache/ibatis/builder/MapperConfig.xml";
final Reader reader = Resources.getResourceAsReader(resource);
SqlSessionFactory sqlMapper = new SqlSessionFactoryBuilder().build(reader);
// 开始执行SQL
SqlSession session = sqlMapper.openSession();
Integer count = session.selectOne("org.apache.ibatis.domain.blog.mappers.BlogMapper.selectCountOfPosts");
System.out.println(count);
}
}
这段代码完成了这些事情:
- 读取Mybatis的配置文件
- 构建SqlSessionFactory
- 从SqlSessionFactory中创建一个SqlSession
- 使用SqlSession执行一个select语句,参数是Mapper.java的一个方法名
- 打印结果
在这里前三行代码包括读取配置文件和创建SqlSessionFactory,这就是Mybatis的一次初始化过程。
如果查看一下Spring配置Mybatis的文件,就会发现它使用mybatis-spring的包也主要是初始化了这个SqlSessionFactory对象:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:conf/MapperConfig.xml" />
<property name="mapperLocations">
<list>
<value>classpath*:mapper
/*.xml</value>
</list>
</property>
</bean>
该Spring配置sqlSessionFactory接收了三个参数,分别是数据源dataSource、Mybatis的主配置文件MapperConfig.xml、mapper.xml文件的扫描路径。
可以看出Mybatis的初始化过程就是读取配置文件然后构建出sqlSessionFactory的过程。
Mybatis都有哪些配置文件和配置项?
上面的Java代码中初始化Mybatis只使用了配置文件MapperConfig.xml,然而在Spring配置文件中构建sqlSessionFactory时也使用了mapper.xml配置文件,其实Mybatis最多也就这两类文件,主配置文件MapperConfig.xml可以通过XML元素包含普通的mapper.xml配置文件。
主配置文件:MapperConfig.xml
一个包含了所有属性的MapperConfig.xml实例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="org/apache/ibatis/databases/blog/blog-derby.properties" />
<settings>
<setting name="cacheEnabled" value="true" />
<setting name="lazyLoadingEnabled" value="false" />
<setting name="multipleResultSetsEnabled" value="true" />
<setting name="useColumnLabel" value="true" />
<setting name="useGeneratedKeys" value="false" />
<setting name="defaultExecutorType" value="SIMPLE" />
<setting name="defaultStatementTimeout" value="25" />
</settings>
<typeAliases>
<typeAlias alias="Author" type="org.apache.ibatis.domain.blog.Author" />
<typeAlias alias="Blog" type="org.apache.ibatis.domain.blog.Blog" />
</typeAliases>
<typeHandlers>
<typeHandler javaType="String" jdbcType="VARCHAR"
handler="org.apache.ibatis.builder.CustomStringTypeHandler" />
</typeHandlers>
<objectFactory type="org.apache.ibatis.builder.ExampleObjectFactory">
<property name="objectFactoryProperty" value="100" />
</objectFactory>
<plugins>
<plugin interceptor="org.apache.ibatis.builder.ExamplePlugin">
<property name="pluginProperty" value="100" />
</plugin>
</plugins>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC">
<property name="" value="" />
</transactionManager>
<dataSource type="UNPOOLED">
<property name="driver" value="${driver}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<property name="password" value="${password}" />
</dataSource>
</environment>
</environments>
<databaseIdProvider type="DB_VENDOR">
<property name="SQL Server" value="sqlserver" />
<property name="DB2" value="db2" />
<property name="Oracle" value="oracle" />
</databaseIdProvider>
<mappers>
<mapper resource="org/apache/ibatis/builder/AuthorMapper.xml" />
<mapper resource="org/apache/ibatis/builder/BlogMapper.xml" />
</mappers>
</configuration>
主配置文件只有一个XML节点,就是configuration,它包含9种配置项:
- properties 属性:在这里配置的属性可以在整个配置文件中使用来替换需要动态配置的属性值
- settings 设置:MyBatis 中极为重要的调整设置,它们会改变 MyBatis 的运行时行为,比如是否使用缓存和日志记录的方式
- typeAliases 类型命名:类型别名是为 Java 类型设置一个短的名字。它只和 XML 配置有关,存在的意义仅在于用来减少类完全限定名的冗余。
- typeHandlers 类型处理器:无论是 MyBatis 在预处理语句(PreparedStatement)中设置一个参数时,还是从结果集中取出一个值时, 都会用类型处理器将获取的值以合适的方式转换成 Java 类型。
- objectFactory 对象工厂:MyBatis 每次创建结果对象的新实例时,它都会使用一个对象工厂(ObjectFactory)实例来完成。
- plugins 插件:MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用,比如增加分页功能、格式化输出最终的SQL等扩展;
- environments 环境:MyBatis 可以配置成适应多种环境,这种机制有助于将 SQL 映射应用于多种数据库之中,比如设置不同的开发、测试、线上配置,在每个配置中可以配置事务管理器和数据源对象;
- databaseIdProvider 数据库厂商标识:MyBatis 可以根据不同的数据库厂商执行不同的语句,这种多厂商的支持是基于映射语句中的 databaseId 属性。
- mappers 映射器:MyBatis 的行为已经由上述元素配置完了,通过这里配置的mappers文件,我们可以去查找定义 的SQL 映射语句用于执行;
可以看出,前8个配置项用户设定Mybatis运行的一些环境,而第9个mappers映射器才是需要执行的SQL的配置,在正常情况下,我们只需要配置第9个mapper映射器的地址即可,前面的的Mybatis行为配置都有默认值正常情况下不需要设定。
包含最终SQL的mapper映射器配置文件
虽然我们经常写mapper文件,知道有select/insert/update/delete四种元素,还有sql/resultmap等配置项,就感觉配置项好多好多,但其实mapper总共也就8种配置,我们常用的6种就包含在内:
- cache – 给定命名空间的缓存配置。
- cache-ref – 其他命名空间缓存配置的引用。
- resultMap – 是最复杂也是最强大的元素,用于实现数据库表列和Java Bean的属性名的映射配置;
- sql – 可被其他语句引用的可重用语句块。
- insert – 映射插入语句
- update – 映射更新语句
- delete – 映射删除语句
- select – 映射查询语句
正常情况下,我们很少使用Mybatis提供的cache机制而是使用外部