SqlSessionFactoryBuilder階段
在程序中第一步就是創建SqlSessionFactoryBuilder對象,調用它的build方法,將全局配置文件傳入,該方法便會返回一個SqlSessionFactory對象
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
在build方法中主要做的工作就是創建XMLConfigBuilder對象,用此對象解析全局配置文件,將解析到的信息封裝到Configuration對象中,並將此對象返回,接着這個Configuration對象會被當做DefaultSqlSessionFactory構造參數傳入,DefaultSqlSessionFactory根據Configuration對象中的信息創建SqlSessionFactory(類似於JDBC中根據用戶名、密碼、url等參數創建連接池一樣)。
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
在這裏可以看到SqlSessionFactory是一個接口,默認使用的是DefaultSqlSessionFactory對象。
至此SqlSessionFactoryBuilder類的全部工作已經完成。
SqlSessionFactory階段
使用上步返回的DefaultSqlSessionFactory對象可以打開一個session會話(類似於在數據庫連接池中獲取到一個連接Connection)
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
final Environment environment = configuration.getEnvironment();
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
final Executor executor = configuration.newExecutor(tx, execType);
return new DefaultSqlSession(configuration, executor, autoCommit);
}
和SqlSessionFactory一樣,SqlSession也是一個接口,它的默認實現是DefaultSqlSession,創建此對象時需要傳入全局配置對象,執行器,是否自動提交三個參數。
SqlSession階段
SqlSession中存在四個關鍵對象:Executor、StatementHandler、ParameterHandler、ResultHandler。
Executor代表調度器,負責使用其他Handler執行sql語句的。
public interface Executor {
ResultHandler NO_RESULT_HANDLER = null;
int update(MappedStatement ms, Object parameter) throws SQLException;
<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
<E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;
List<BatchResult> flushStatements() throws SQLException;
void commit(boolean required) throws SQLException;
void rollback(boolean required) throws SQLException;
CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
boolean isCached(MappedStatement ms, CacheKey key);
void clearLocalCache();
void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);
Transaction getTransaction();
void close(boolean forceRollback);
boolean isClosed();
void setExecutorWrapper(Executor executor);
}
StatementHandler代表語句處理器,類似於PrepardStatement。
public interface StatementHandler {
Statement prepare(Connection connection, Integer transactionTimeout)
throws SQLException;
void parameterize(Statement statement)
throws SQLException;
void batch(Statement statement)
throws SQLException;
int update(Statement statement)
throws SQLException;
<E> List<E> query(Statement statement, ResultHandler resultHandler)
throws SQLException;
<E> Cursor<E> queryCursor(Statement statement)
throws SQLException;
BoundSql getBoundSql();
ParameterHandler getParameterHandler();
}
ParameterHandler代表參數處理器,負責處理參數到sql佔位符的轉化。
public interface ParameterHandler {
Object getParameterObject();
void setParameters(PreparedStatement ps)
throws SQLException;
}
ResultHandler負責封裝返回的數據。
public interface ResultHandler<T> {
void handleResult(ResultContext<? extends T> resultContext);
}
最後通過一張圖將所有的流程串起來
在sqlSession階段主要做的事情是獲取Mapper接口,調用Mapper中的方法,處理返回結果。
DeptMapper mapper = sqlSession.getMapper(DeptMapper.class);
HashMap<String, Integer> map = new HashMap<>();
map.put("deptNo",1);
Dept dept = mapper.selectDept(map);
System.out.println(dept);
sqlSession.commit();
最重要的地方在於Mapper的獲取和使用上。
Mapper階段
mapper底層是使用動態代理技術創建對象的,對應的類爲MapperProxy,一個Mapper配置文件對應着三個類,分別爲MappedStatement、SqlSource、BoundSql。
MappedStatement代表着配置文件中insert、select、delete、update標籤和標籤裏設置的屬性值
public final class MappedStatement {
private String resource;
private Configuration configuration;
private String id;
private Integer fetchSize;
private Integer timeout;
private StatementType statementType;
private ResultSetType resultSetType;
private SqlSource sqlSource;
private Cache cache;
private ParameterMap parameterMap;
private List<ResultMap> resultMaps;
private boolean flushCacheRequired;
private boolean useCache;
private boolean resultOrdered;
private SqlCommandType sqlCommandType;
private KeyGenerator keyGenerator;
private String[] keyProperties;
private String[] keyColumns;
private boolean hasNestedResultMaps;
private String databaseId;
private Log statementLog;
private LanguageDriver lang;
private String[] resultSets;
}
sqlSource用來提供BoundSql對象,它是作爲MappedStatement的屬性存在的。
public interface SqlSource {
BoundSql getBoundSql(Object parameterObject);
}
BoundSql 代表了一條sql以及對應的參數,它使用sql屬性表示寫在標籤裏的sql語句
public class BoundSql {
private final String sql;
private final List<ParameterMapping> parameterMappings;
private final Object parameterObject;
private final Map<String, Object> additionalParameters;
private final MetaObject metaParameters;
}