mybatis源码剖析

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;
    }
}

这样就得到了结果!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值