使用Mybatis操作数据库的基本写法如下:
@Test
public void testMybatis(){
//1.加载配置文件
InputStream resourceAsStream = Resources.getResourceAsStream("sqlMapConfig.xml");
//建造者设计模式
//2.解析配置文件,封装成Configuration 创建DefaultSqlSessionFactory对象
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(resourceAsStream);
//3.生产了DefaultSqlsession实例对象
SqlSession sqlSession = sqlSessionFactory.openSession();
//传统方式,根statementid从map中获取MappedStatement对象
//List
//4.代理方式,得到代理类对象
AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
//5.完成crud
List<Account>list = accountDao.findAll();
...
}
}
SqlSession是应用程序和mybatis交互的核心接口,而创建SqlSession对象之前还有一系列的前序操作,包括:
加载配置文件,由Resources.getResourceAsStream()完成。应用程序需要提供给Mybatis的配置文件有核心配置文件(上面程序中的sqlMapConfig.xml,实际使用不一定是这个名称),以及映射配置文件(一般会命名为xxxMapper.xml),映射配置文件的路径会配置在核心配置文件的
创建SqlSessionFactoryBuilder对象,从应用程序的角度看,该对象完成了两个任务:
将配置文件解析为Configuration对象
创建SqlSessionFactory对象,将Configuration对象传递给SqlSessionFactory对象,并返回SqlSessionFactory对象
SqlSessionFactory对象主要用于生产SqlSession
使用SqlSessionFactoryBuilder的入口是SqlSessionFactoryBuilder.build()方法
具体实现如下:
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
//创建XMLConfigBuilder,用于解析mybatis配置文件
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
//解析配置文件得到Configuration对象,创建DefaultSqlSessionFactory对象
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
而这个方法在返回时调用的build()方法实现如下:
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
显然,SqlSessionFactoryBuilder中的重点在配置文件解析上,回到最初的build()方法,里面创建了一个XMLConfigBuilder对象,而XMLConfigBuilder对象继承自BaseBuilder,事实上,在上一章提到的Mybatis整体架构中,核心处理层的配置解析,主要就是由BaseBuilder及其子类完成的。
BaseBuilder中定义了以下三个属性:
public abstract class BaseBuilder {
//configuration保存Mybatis中几乎全部的配置信息,
protected final Configuration configuration;
//核心配置文件可以使用标签定义别名,别名会记录在typeAliasRegistry对象中
protected final TypeAliasRegistry typeAliasRegistry;
//核心配置文件可以使用标签添加自定义TypeHandler器,完成指定数据库类型与Java类型的转换
//这些TypeHandler会记录在typeHandlerRegistry中
protected final TypeHandlerRegistry typeHandlerRegistry;
...
另外BaseBuilder中的parseExpression用于解析配置文件中的正则表达式,booleanValueOf,integerValueOf,stringSetValueOf方法,从定义上看,应该是用于转换配置文件中的属性值字符串的类型,并且在没有配置属性的时候就使用默认值。
protected Pattern parseExpression(String regex, String defaultValue) {
return Pattern.compile(regex == null ? defaultValue : regex);
}
protected Boolean booleanValueOf(String value, Boolean defaultValue) {
return value == null ? defaultValue : Boolean.valueOf(value);
}
protected Integer integerValueOf(String value, Integer defaultValue) {
return value == null ? defaultValue : Integer.valueOf(value);
}
protected Set<String> stringSetValueOf(String value, String defaultValue) {
value = value == null ? defaultValue : value;
return new HashSet<>(Arrays.asList(value.split(",")));
}
此外,resolveAlias()方法用于解析别名,resolveTypeHandler()方法查找指定的TypeHandler对象。
resolveJdbcType(),resolveResultSetType(),resolveParameterMode()这几个方法会将String转换为对应的JdbcType枚举类型、ResultSetType枚举类和ParameterMode枚举类,此处不做赘述,之后还会提到。
XMLConfigBuilder完成了解析核心配置文件的任务。在Mybatis的核心配置文件中,主要有以下几种标签:
properties 属性
settings 设置
typeAliases 类型别名
typehandlers 类型处理器
objectFactory 对象工厂
plugins 插件
environments 环境
databaseidProvider 数据库厂商标识
mappers 映射器
进行解析的入口是XMLConfigBuilder.parse()方法,会调用XpathParser对象将根标签进行解析,传给XMLConfigBuilder.parseConfiguration()方法:
public Configuration parse() {
//如果已解析,抛出BuilderException异常
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
//parser是XpathParser解析器对象,读取节点内数据
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
XMLConfigBuilder.parseConfiguration()逐个对每个子标签调用对应的解析方法,下一章中将重点关注XMLConfigBuilder.mapperElement()方法,该方法用于对mapper标签进行解析。