Mybatis工作流程及其原理与解析

public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {

try {

XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);

//解析mybatis-config.xml

return build(parser.parse());

} catch (Exception e) {

throw ExceptionFactory.wrapException(“Error building SqlSession.”, e);

} finally {

ErrorContext.instance().reset();

try {

inputStream.close();

} catch (IOException e) {

// Intentionally ignore. Prefer previous error.

}

}

}

//返回SqlSessionFactory,默认使用的是实现类DefaultSqlSessionFactory

public SqlSessionFactory build(Configuration config) {

return new DefaultSqlSessionFactory(config);

}

public Configuration parse() {

if (parsed) {

throw new BuilderException(“Each XMLConfigBuilder can only be used once.”);

}

parsed = true;

//获取根节点configuration

parseConfiguration(parser.evalNode(“/configuration”));

return configuration;

}

//开始解析mybatis-config.xml,并把解析后的数据存放到configuration中

private void parseConfiguration(XNode root) {

try {

//保存mybatis-config.xml中的标签setting,本例中开启全局缓存cacheEnabled,设置默认执行器defaultExecutorType=REUSE

Properties settings = settingsAsPropertiess(root.evalNode(“settings”));

//issue #117 read properties first

//解析是否配置了外部properties,例如本例中配置的jdbc.propertis

propertiesElement(root.evalNode(“properties”));

//查看是否配置了VFS,默认没有,本例也没有使用

loadCustomVfs(settings);

//查看是否用了类型别名,减少完全限定名的冗余,本例中使用了别名User代替了com.ctc.Model.User

typeAliasesElement(root.evalNode(“typeAliases”));

//查看是否配置插件来拦截映射语句的执行,例如拦截Executor的Update方法,本例没有使用

pluginElement(root.evalNode(“plugins”))

//查看是否配置了ObjectFactory,默认情况下使用对象的无参构造方法或者是带有参数的构造方法,本例没有使用

objectFactoryElement(root.evalNode(“objectFactory”));

//查看是否配置了objectWrapperFatory,这个用来或者ObjectWapper,可以访问:对象,Collection,Map属性。本例没有使用

objectWrapperFactoryElement(root.evalNode(“objectWrapperFactory”));

//查看是否配置了reflectorFactory,mybatis的反射工具,提供了很多反射方法。本例没有使用

reflectorFactoryElement(root.evalNode(“reflectorFactory”));

//放入参数到configuration对象中

settingsElement(settings);

// read it after objectFactory and objectWrapperFactory issue #631

//查看数据库环境配置

environmentsElement(root.evalNode(“environments”));

//查看是否使用多种数据库,本例没有使用

databaseIdProviderElement(root.evalNode(“databaseIdProvider”));

//查看是否配置了新的类型处理器,如果跟处理的类型跟默认的一致就会覆盖。本例没有使用

typeHandlerElement(root.evalNode(“typeHandlers”));

//查看是否配置SQL映射文件,有四种配置方式,resource,url,class以及自动扫包package。本例使用package

mapperElement(root.evalNode(“mappers”));

} catch (Exception e) {

throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);

}

}

第二步通过SqlSessionFactory创建SqlSession:

@Override

public SqlSession openSession() {

return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);

}

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {

Transaction tx = null;

try {

//拿到前文从mybatis中解析到的数据库环境配置

final Environment environment = configuration.getEnvironment();

final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);

//拿到jdbc的事务管理器,有两种一种是jbc,一种的managed。本例使用的是JdbcTransaction

tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);

//从mybatis配置文件可以看到本例使用了REUSE,因此返回的是ReuseExecutor并把事务传入对象中

final Executor executor = configuration.newExecutor(tx, execType);

return new DefaultSqlSession(configuration, executor, autoCommit);

} catch (Exception e) {

closeTransaction(tx); // may have fetched a connection so lets call close()

throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);

} finally {

ErrorContext.instance().reset();

}

}

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 {

executor = new SimpleExecutor(this, transaction);

}

if (cacheEnabled) {

executor = new CachingExecutor(executor);

}

executor = (Executor) interceptorChain.pluginAll(executor);

return executor;

}

//返回一个SqlSession,默认使用DefaultSqlSession

public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {

this.configuration = configuration;

this.executor = executor;

this.dirty = false;

this.autoCommit = autoCommit;

}

第三步通过SqlSession拿到Mapper对象的代理:

@Override

public T getMapper(Class type) {

return configuration.getMapper(type, this);

}

public T getMapper(Class type, SqlSession sqlSession) {

//前文解析Mybatis-config.xml的时候,在解析标签mapper就是用configuration对象的mapperRegistry存放数据

return mapperRegistry.getMapper(type, sqlSession);

}

@SuppressWarnings(“unchecked”)

public T getMapper(Class type, SqlSession sqlSession) {

//knownMapper是一个HashMap在存放mapperRegistry的过程中,以每个Mapper对象的类型为Key, MapperProxyFactory 为value保存。

//例如本例中保存的就是Key:com.ctc.mapper.UserMapper,value就是保存了key的MapperProxyFactory对象

final MapperProxyFactory mapperProxyFactory = (MapperProxyFactory) knownMappers.get(type);

if (mapperProxyFactory == null) {

throw new BindingException(“Type " + type + " is not known to the MapperRegistry.”);

}

try {

return mapperProxyFactory.newInstance(sqlSession);

} catch (Exception e) {

throw new BindingException("Error getting mapper instance. Cause: " + e, e);

}

}

public T newInstance(SqlSession sqlSession) {

//生成一个mapperProxy对象,这个对象实现了InvocationHandler, Serializable。就是JDK动态代理中的方法调用处理器

final MapperProxy mapperProxy = new MapperProxy(sqlSession, mapperInterface, methodCache);

return newInstance(mapperProxy);

}

public MapperProxy(SqlSession sqlSession, Class mapperInterface, Map methodCache) {

this.sqlSession = sqlSession;

this.mapperInterface = mapperInterface;

this.methodCache = methodCache;

}

@SuppressWarnings(“unchecked”)

protected T newInstance(MapperProxy mapperProxy) {

//通过JDK动态代理生成一个Mapper的代理,在本例中的就是UserMapper的代理类,它实现了UserMapper接口

return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);

}

第四步通过MapperProxy调用Maper中相应的方法:

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

//判断当前调用的method是不是Object中声明的方法,如果是的话直接执行。

if (Object.class.equals(method.get 《一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义》无偿开源 威信搜索公众号【编程进阶路】 DeclaringClass())) {

try {

return method.invoke(this, args);

} catch (Throwable t) {

throw ExceptionUtil.unwrapThrowable(t);

}

}

final MapperMethod mapperMethod = cachedMapperMethod(method);

return mapperMethod.execute(sqlSession, args);

}

//把当前请求放入一个HashMap中,一旦下次还是同样的方法进来直接返回。

private MapperMethod cachedMapperMethod(Method method) {

MapperMethod mapperMethod = methodCache.get(method);

if (mapperMethod == null) {

mapperMethod = new MapperMethod(mapperInterface, method, sqlSession.getConfiguration());

methodCache.put(method, mapperMethod);

}

return mapperMethod;

}

public Object execute(SqlSession sqlSession, Object[] args) {

Object result;

switch (command.getType()) {

case INSERT: {

Object param = method.convertArgsToSqlCommandParam(args);

result = rowCountResult(sqlSession.insert(command.getName(), param));

break;

}

case UPDATE: {

Object param = method.convertArgsToSqlCommandParam(args);

result = rowCountResult(sqlSession.update(command.getName(), param));

break;

}

case DELETE: {

Object param = method.convertArgsToSqlCommandParam(args);

result = rowCountResult(sqlSession.delete(command.getName(), param));

break;

}

case SELECT:

if (method.returnsVoid() && method.hasResultHandler()) {

executeWithResultHandler(sqlSession, args);

result = null;

} else if (method.returnsMany()) {

result = executeForMany(sqlSession, args);

} else if (method.returnsMap()) {

result = executeForMap(sqlSession, args);

} else if (method.returnsCursor()) {

result = executeForCursor(sqlSession, args);

} else {

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值