mybatis源码剖析
mybatis开发demo
InputStream resourceAsStream = Resources.getResourceAsStream("mybatis-config.xml");
//获取SqlSessionFactoryBuilder
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
//解析配置文件,获得SqlSessionFactory
SqlSessionFactory sqlSessionFactory = builder.build(resourceAsStream);
//SqlSessionFactory获得SqlSession
SqlSession sqlSession = sqlSessionFactory.openSession();
//获得对应的映射文件
DormDao mapper = sqlSession.getMapper(DormDao.class);
//调用对应方法
Dorm dorm = mapper.selectByPrimaryKey("A1-102");
1、解析配置文件,得到SqlSessionFactory
得到SqlSessionFactoryBuilder之后就是解析xml文件
//build方法体
//此时的environment以及properties都是null
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
SqlSessionFactory var5;
try {
//获得xml解析类,负责解析文件
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
//解析的方法
//先parse调用parse()方法
//解析好之后通过build()方法返回DefaultSqlSessionFactory,这个就是真正需要的SqlSessionFactory
var5 = this.build(parser.parse());
} catch (Exception var14) {
throw ExceptionFactory.wrapException("Error building SqlSession.", var14);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException var13) {
}
}
return var5;
}
parse方法解析xml
//解析配置文件,返回Configuration
//Configuration是DefaultSqlSessionFactory的属性
//保存配置文件的信息
public Configuration parse() {
//不可重复解析xml
if (this.parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
} else {
//标志位设置
this.parsed = true;
//实际解析位置
//标记此时解析的位置是configuration
//将所有的解析好的配置信息加载到configuration中返回出去
this.parseConfiguration(this.parser.evalNode("/configuration"));
return this.configuration;
}
}
在得到DefaultSqlSessionFactory时,已经将xml文件加载到其属性configuration中了
2、创建sqlsession
在调用sqlsessionFactory的openSession实际上是调用的是DefaultSqlSessionFactory的openSessionFromDataSource方法
//execType默认为simple,即执行器为simple类型,还有reuse、batch类型、
//事物隔离级别默认为null
//自动提交为false
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
DefaultSqlSession var8;
try {
//获取environment
Environment environment = this.configuration.getEnvironment();
//从环境中获取事物信息的工厂类,如果有配置的话
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
//得到事物处理
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//创建执行器,工作了三件事
//配置执行器类型
//如果开启二级缓存,就生成二级缓存包装类
//设置拦截器
Executor executor = this.configuration.newExecutor(tx, execType);
//创建sqlsession,包含了configuration,一级执行器
var8 = new DefaultSqlSession(this.configuration, executor, autoCommit);
} catch (Exception var12) {
this.closeTransaction(tx);
throw ExceptionFactory.wrapException("Error opening session. Cause: " + var12, var12);
} finally {
ErrorContext.instance().reset();
}
//返回生成默认的sqlsession
return var8;
}
通过该方法会得到一个包含了configuration,执行器executor的sqlsession,另外二级缓存在此生成
3、获取对应的Mapper
此时调用getmapper返回得到的是一个代理类
4、执行方法体
知道此时的mapper只是一个代理类之后,真正运行的必定是该代理类的invoke()方法
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
if (this.isDefaultMethod(method)) {
return this.invokeDefaultMethod(proxy, method, args);
}
} catch (Throwable var5) {
throw ExceptionUtil.unwrapThrowable(var5);
}
//将方法添加到自带的缓存中加上创建MapperMethod
//MapperMethod就俩个属性
//command:保存方法的名字加上类型
//method保存方法的放回类型等信息
MapperMethod mapperMethod = this.cachedMapperMethod(method);
//执行方法体
return mapperMethod.execute(this.sqlSession, args);
}
execute()方法
public Object execute(SqlSession sqlSession, Object[] args) {
Object param;
Object result;
//判断此时语句的类型
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:
//是SELECT类型,就调用对应的方法
//当返回的void
if (this.method.returnsVoid() && this.method.hasResultHandler()) {
this.executeWithResultHandler(sqlSession, args);
result = null;
//返回是一个list
} else if (this.method.returnsMany()) {
result = this.executeForMany(sqlSession, args);
//返回是一个map
} 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);
}
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;
}
}
这样就得到了结果!