使用Mybatis操作數據庫
使用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<Object> list = sqlSession.selectList("com.mybaits.test.AccountDao.findAll");
//4.代理方式,得到代理類對象
AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
//5.完成crud
List<Account>list = accountDao.findAll();
...
}
}
SqlSession是應用程序和mybatis交互的核心接口,而創建SqlSession對象之前還有一系列的前序操作,包括:
-
加載配置文件,由Resources.getResourceAsStream()完成。應用程序需要提供給Mybatis的配置文件有核心配置文件(上面程序中的sqlMapConfig.xml,實際使用不一定是這個名稱),以及映射配置文件(一般會命名爲xxxMapper.xml),映射配置文件的路徑會配置在覈心配置文件的<mappers>標籤下,所以外部加載的時候只加載核心配置文件就夠了。在之後的解析過程中,核心配置文件大部分內容會被保存在全局唯一的Configuration對象中
-
創建SqlSessionFactoryBuilder對象,從應用程序的角度看,該對象完成了兩個任務:
-
將配置文件解析爲Configuration對象
-
創建SqlSessionFactory對象,將Configuration對象傳遞給SqlSessionFactory對象,並返回SqlSessionFactory對象
-
-
SqlSessionFactory對象主要用於生產SqlSession
SqlSessionFactoryBuilder
使用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);
}
BaseBuilder
顯然,SqlSessionFactoryBuilder中的重點在配置文件解析上,回到最初的build()方法,裏面創建了一個XMLConfigBuilder對象,而XMLConfigBuilder對象繼承自BaseBuilder,事實上,在上一章提到的Mybatis整體架構中,核心處理層的配置解析,主要就是由BaseBuilder及其子類完成的。
查看BaseBuilder的繼承與依賴關係,如下圖所示:
BaseBuilder中定義了以下三個屬性:
public abstract class BaseBuilder {
//configuration保存Mybatis中幾乎全部的配置信息,
protected final Configuration configuration;
//核心配置文件可以使用<typeAliases>標籤定義別名,別名會記錄在typeAliasRegistry對象中
protected final TypeAliasRegistry typeAliasRegistry;
//核心配置文件可以使用<typeHandlers>標籤添加自定義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
XMLConfigBuilder完成了解析核心配置文件的任務。在Mybatis的核心配置文件中,主要有以下幾種標籤:
-
properties 屬性
-
settings 設置
-
typeAliases 類型別名
-
typehandlers 類型處理器
-
objectFactory 對象工廠
-
plugins 插件
-
environments 環境
- enviroment 環境變量
- transactionManager 事務管理器
- dataSource 數據源
- enviroment 環境變量
-
databaseidProvider 數據庫廠商標識
-
mappers 映射器
XMLConfigBuilder也比較清晰地定義了每個標籤的解析方法:
進行解析的入口是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標籤進行解析。