Sqlsession中包含了Configuration对象,可以拿到全局配置信息。
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory#openSession()
public SqlSession openSession() {
return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
}
二、获取执行器
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? this.defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Object executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
if (this.cacheEnabled) {
executor = new CachingExecutor((Executor)executor);
}
Executor executor = (Executor)this.interceptorChain.pluginAll(executor);
return executor;
}
执行器分为两大类:一类是CacheExecutor,另一类是普通Executor。
普通Executor又有三种实现:
(1)simpleExecutor:每执行一次update或者select,就开启一个Statement对象,用完就立刻关闭Statement对象。
(2)ReuseExecutor:执行update或者select操作,以sql作为key查找statement对象,存在就重复利用,不存在就存入map中。
(3)BatchExecutor:将所有的sql都添加在批处理对象中,等待统一执行,它缓存了多个Statement对象,等待executeBatch()批处理。
CacheExecutor封装了普通Executor,区别是查询前会先查询缓存中是否有结果,如果缓存中有就从缓存中拿,没有的话,使用普通executor执行,再把结果放入缓存中。
三、获取mapperorg.apache.ibatis.session.defaults.DefaultSqlSession#getMapper
public <T> T getMapper(Class<T> type) {
return this.configuration.getMapper(type, this);
}
由于mapper是一个接口所以会生成一个动态代理类。
public static <T> T newMapperProxy(Class<T> mapperInterface, SqlSession sqlSession) {
ClassLoader classLoader = mapperInterface.getClassLoader();
Class<?>[] interfaces = new Class[]{mapperInterface};
MapperProxy proxy = new MapperProxy(sqlSession);
return Proxy.newProxyInstance(classLoader, interfaces, proxy);
}
四、mapper的调用
执行代理后的execute方法,根据mapper.xml中配置的操作标签类型,执行对象的sqlsession的增删改查方法。
public Object execute(Object[] args) {
Object result = null;
Object param;
if (SqlCommandType.INSERT == this.type) {
param = this.getParam(args);
result = this.sqlSession.insert(this.commandName, param);
} else if (SqlCommandType.UPDATE == this.type) {
param = this.getParam(args);
result = this.sqlSession.update(this.commandName, param);
} else if (SqlCommandType.DELETE == this.type) {
param = this.getParam(args);
result = this.sqlSession.delete(this.commandName, param);
} else {
if (SqlCommandType.SELECT != this.type) {
throw new BindingException("Unknown execution method for: " + this.commandName);
}
if (this.returnsVoid && this.resultHandlerIndex != null) {
this.executeWithResultHandler(args);
} else if (this.returnsList) {
result = this.executeForList(args);
} else if (this.returnsMap) {
result = this.executeForMap(args);
} else {
param = this.getParam(args);
result = this.sqlSession.selectOne(this.commandName, param);
}
}
return result;
}
sqlsession底层会调用executor的增删改查方法,这里以update方法为例。
public int update(String statement, Object parameter) {
int var4;
try {
this.dirty = true;
MappedStatement ms = this.configuration.getMappedStatement(statement);
var4 = this.executor.update(ms, this.wrapCollection(parameter));
} catch (Exception var9) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + var9, var9);
} finally {
ErrorContext.instance().reset();
}
return var4;
}
实际调用的是simpleExecutor的doUpdate方法
public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
int var6;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, (ResultHandler)null);
stmt = this.prepareStatement(handler);
var6 = handler.update(stmt);
} finally {
this.closeStatement(stmt);
}
return var6;
}
然后是调用PreparedStatementHandler类中的方法,有点类似于我们直接jdbc的调用写法了。
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement)statement;
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = this.boundSql.getParameterObject();
KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator();
keyGenerator.processAfter(this.executor, this.mappedStatement, ps, parameterObject);
return rows;
}
query的调用更能说明问题:
public List query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement)statement;
ps.execute();
return this.resultSetHandler.handleResultSets(ps);
}
总结:其实就是对jdbc的层层封装和功能完善。