a.获取SqlSessionFactory对象
b.获取SqlSession对象
c.获取Mapper对象(代理接口中的方法、mapper.xml中的标签)
d.执行标签中定义的SQL语句
String resource = "conf.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
parser解析器
通过parseConfiguration()在configuration设置了 properties、settings,environments等属性标签
解析setting标签
解析mapper.xml标签
解析sql标签
将sql标签解析成MappedStatement对象
通过MappedStatement属性可以发现,其就是sql标签的对象
发现parse解析器解析后返回的是Configuration对象
查看Configuration,发现包含了所有的配置信息和MappedStatement对象
返回Configuration对象后通过build方法返回一个DefaultSqlSessionFactory对象
DefaultSqlSessionFactory是SqlSessionFactory的一个实现类,所有默认使用的sqlSessionFactory对象其实是DefaultSqlSessionFactory。
SqlSession sqlSession = sqlSessionFactory.openSession();
openSession()调用openSessionFromDataSource
通过Configuration获得执行器类型,并可以发现默认是SIMPLE.
Executor executor = this.configuration.newExecutor(tx, execType);
DefaultSqlSession(this.configuration, executor, autoCommit);
发现除了返回一个DefaultSqlSession(SqlSession的实现类,包含配置信息,执行器,事务)还通过Configuration对象生成了一个执行器
Executor executor = (Executor)this.interceptorChain.pluginAll(executor);
Configuration 通过不同的executorType和事务生成不同类型的执行器,并且会被拦截器/链(interceptorChain)拦截并装饰(pluginAll(executor))。
大致流程
openSession()->openSessionFromDataSource()->DefaultSqlSession对象
Mapper注册器,通过mapperProxyFactory生成mapperProxy
生成mapperProxy
MapperProxy对象
JDK动态代理接口
发现用到了动态代理模式用 MapperProxy代理对象执行sql操作
执行
MapperMethod mapperMethod = this.cachedMapperMethod(method);
return mapperMethod.execute(this.sqlSession, args);
mapperMethod.execute(sqlSession,args) :实际调用增删改查的方法 ,依靠于sqlSession中的configuration和 executor
SqlSession(configuration,executor,事务)、
MapperInterface 代理接口的对象
methodCache(存放查询缓存, 底层是CurrentHashMap)
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
Object param;
switch(this.command.getType()) {
case INSERT:
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.insert(this.command.getName(), param));
break;
case UPDATE:
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.update(this.command.getName(), param));
break;
case DELETE:
param = this.method.convertArgsToSqlCommandParam(args);
result = this.rowCountResult(sqlSession.delete(this.command.getName(), param));
break;
case SELECT:
if (this.method.returnsVoid() && this.method.hasResultHandler()) {
this.executeWithResultHandler(sqlSession, args);
result = null;
} else if (this.method.returnsMany()) {
result = this.executeForMany(sqlSession, args);
} else if (this.method.returnsMap()) {
result = this.executeForMap(sqlSession, args);
} else if (this.method.returnsCursor()) {
result = this.executeForCursor(sqlSession, args);
} else {
param = this.method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(this.command.getName(), param);
if (this.method.returnsOptional() && (result == null || !this.method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + this.command.getName());
}
if (result == null && this.method.getReturnType().isPrimitive() && !this.method.returnsVoid()) {
throw new BindingException("Mapper method '" + this.command.getName() + " attempted to return null from a method with a primitive return type (" + this.method.getReturnType() + ").");
} else {
return result;
}
}
查询的直接实现
result = this.executeForMany(sqlSession, args);
Object param = this.method.convertArgsToSqlCommandParam(args);
处理增删改查方法的参数:method.convertArgsToSqlCommandParam(args)
如果参数是0个,reutrun null ;
如果参数是1,返回第一个 ;
如果有多个参数 放入map中
sqlSession.selectList 是借助于sqlSession的executor执行器查询的
执行器的查询
boundSql :将我们写的SQL 和 参数值进行了拼接后的对象,即最终能被真正执行的SQL
CacheKey key = this.createCacheKey(ms, parameterObject, rowBounds, boundSql);
list = this.delegate.query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
delegate 是一个执行器
public List query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (this.closed) {
throw new ExecutorException("Executor was closed.");
} else {
if (this.queryStack == 0 && ms.isFlushCacheRequired()) {
this.clearLocalCache();
}
List list;
try {
++this.queryStack;
list = resultHandler == null ? (List)this.localCache.getObject(key) : null;
if (list != null) {
this.handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
list = this.queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
--this.queryStack;
}
if (this.queryStack == 0) {
Iterator var8 = this.deferredLoads.iterator();
while(var8.hasNext()) {
BaseExecutor.DeferredLoad deferredLoad = (BaseExecutor.DeferredLoad)var8.next();
deferredLoad.load();
}
this.deferredLoads.clear();
if (this.configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
this.clearLocalCache();
}
}
return list;
}
}
delegate 的 query
list = this.queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
如果缓存中没有要查询的内容,则进入数据库 真实查询:queryFromDatabase()
StatementHandler处理器
发现默认是RoutingStatementHandler
this.delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
进入 PreparedStatementHandler
像传统JDBC操作
mybatis使用的jdbc对象是PreparedStatement
底层执行增删改查:PreparedStatement的execute()
return this.resultSetHandler.handleResultSets(ps);
MyBatis底层在执行CRUD时 可能会涉及到四个处理器:StatementHandler ParameterHandler TypeHandler ResultSetHandler