目录
前言 mybatis重要类解析
1、mybatis的sql执行代码总览
2、创建session工厂实例解析
3、创建session解析
4、执行查询操作解析
5、session关闭解析
Executor:SQL执行操作的接口定义;
BaseExecutor:抽象类,内部实现了一级缓存,采用了模版模式设计;
SimpleExecutor:sql操作的具体实现类,框架默认的执行器,直接操作数据库;
CachingExecutor:二级缓存实现类,采用了静态代理模式,只做二级缓存处理,sql的具体操作交给SimpleExecutor实现;
Cache:缓存接口定义;
PerpetualCache:缓存具体实现类,采用hashmap实现数据缓存;
SynchronziedCache:采用了静态代理模式,具体的数据缓存交给PerpetualCache实现;
String resource = "mybatis-config.xml";
//读取myabtis核心配置文件
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建session工厂实例
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream,"dev");
//创建session
SqlSession session = sqlSessionFactory.openSession();
try {
Map params =new HashMap();
params.put("code","441");
//执行查询操作
Tz_disease_item blog = (Tz_disease_item) session.selectOne("com.test.dao.DiseaseItemMapper.getDiseaseItemXml", params);
} finally {
//关闭session
session.close();
}
XMLConfigBuilder类,解析mybatis-config.xml核心配置文件
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
//解析properties放入到configuration
propertiesElement(root.evalNode("properties"));
//解析settings放入到configuration
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(settings);
//解析类的别名配置
typeAliasesElement(root.evalNode("typeAliases"));
//MyBatis允许你在已映射语句执行过程中的某一点进行拦截调用
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// 解析数据库配置环境
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
//返回结果从数据库类型到java类型处理器
typeHandlerElement(root.evalNode("typeHandlers"));
//sqlmap文件解析加载
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
1、创建Transaction对象
通过Environment创建一个事务工厂,由工厂来创建Transaction对象
2、创建Executor对象
源码类Configuration
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
//默认的sql执行器
executor = new SimpleExecutor(this, transaction);
}
if (cacheEnabled) {
//默认开启二级缓存
executor = new CachingExecutor(executor);
}
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
通过传入事务对象和Executor的执行类型来创建Executor,executor的默认执行类型ExecutorType.SIMPLE。在创建SimpleExecutor对象时默认调用父类的构造方法实例化一级缓存;
sql的执行器相关的类采用了模版模式设计
Executor:执行sql接口的定义
BaseExecutor:抽象类,提供增删改查对外的接口,不负责具体实现,并内置一级缓存;
CachingExecutor:提供增删改查对外的接口,不负责具体实现,并内置二级缓存;
SimpleExecutor:增删改查的具体实现类,直接操作数据库;
3、创建DefaultSqlSession对象
1、DefaultSqlSession类
1> 通过传如的命名空间和sql的id找到对应的SQL操作类MappedStatement;
2> wrapCollection对传如的参数做处理
如果传如的不是map,将转换为map;
@Override
public List selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
//找到SQL操作类,SQL操作类在哪里初始化?
MappedStatement ms = configuration.getMappedStatement(statement);
//执行SQL语句
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
2、CachingExecutor类,内置了二级缓存
1>CacheKey 的实体包括
(1)sql语句的命名空间和id
(2)分页开始位置
(3)查询数据量
(4)查询语句
(5)入参
(6)数据库环境
将引用对象作为hashmap的key特殊说明,CacheKey重写了equals和hashCode方法,用来确保创建的两个实例在hashmap中能取到相同的值,具体可研究hashmap源码。
@Override
public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
//得到SQL语句
BoundSql boundSql = ms.getBoundSql(parameterObject);
//创建缓存的key实体
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
//执行查询操作
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
public List query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql)
throws SQLException {
Cache cache = ms.getCache();
if (cache != null) {
flushCacheIfRequired(ms);
if (ms.isUseCache() && resultHandler == null) {
ensureNoOutParams(ms, boundSql);
//先从二级缓存取值
@SuppressWarnings("unchecked")
List list = (List) tcm.getObject(cache, key);
if (list == null) {
list = delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
//将查询结果放入到一个临时hashmap中,在session提交或关闭时放入二级缓存
tcm.putObject(cache, key, list); // issue #578 and #116
}
return list;
}
}
return delegate. query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
BaseExecutor类,内置了一级缓存
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 (closed) {
throw new ExecutorException("Executor was closed.");
}
if (queryStack == 0 && ms.isFlushCacheRequired()) {
clearLocalCache();
}
List list;
try {
queryStack++;
//先从一级缓存取
list = resultHandler == null ? (List) localCache.getObject(key) : null;
if (list != null) {
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
queryStack--;
}
return list;
}
private List queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List list;
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
localCache.removeObject(key);
}
//从数据库查询出结果后放入到一级缓存
localCache.putObject(key, list);
if (ms.getStatementType() == StatementType.CALLABLE) {
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
session在关闭时会清空一级缓存,并将查询结果放入到二级缓存;
TransactionalCache类,将查询结果放入到二级缓存
private void flushPendingEntries() {
for (Map.Entry
BaseExecutor类,清空一级缓存
public void clearLocalCache()
if (!closed) {
localCache.clear();
localOutputParameterCache.clear();
}
}