MyBatis的SqlSession使用总结概述

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lichunericli/article/details/82315734

SqlSession是MyBatis中最重要的一个类,它可用来执行SQL,获取映射器,管理事务等。通常应用程序中使用的MyBatis的API就是SqlSession定义的方法。SqlSession下的四大对象:Executor,StatementHandler,ParameterHandler,ResultHandler;MyBatis的核心围绕着这四大对象展开。

MyBatis支持的是内存分页查询,故SelSession中提供的查询方法+RowBounds逻辑分页应该是存在性能问题的【根据具体情况采用物理分页】。

SqlSession的创建很具典型性,由SqlSessionFactoryBuilder创建SqlSessionFactory,然后由SqlSessionFactory来创建SqlSession。SqlSessioFactory的创建可以通过Reader实例,InputStream和Configuration。Reader实例最常用,通常可以使用相关XML文件的Reader实例,可选的参数是environment和properties;Environment决定加载哪种环境(开发环境/生产环境),包括数据源和事务管理器,如果使用properties,那么就会加载那些properties属性配置文件,属性可以用${propName}语法形式多次用在配置文件中。

MyBatis有提供SqlSessionManager来管理SqlSessionFactory和SqlSession。由源码可以看出SqlSession的应用是线程隔离的,通过ThreadLocal来实现的;SqlSessionManager也有提供SqlSession的代理来实现SqlSession中某些对应的方法。在SqlSessionManager中存在内部类SqlSessionInterceptor实现了InvocationHandler来实现对SqlSession的拦截。

DefaultSqlSessionFactory中提供了从DataSource和从Connection两种方法来获取默认的SqlSession。其获取SqlSession方法类似,都是先从Configuration中获取Environment,然后从Environment中来获取事务工厂TransactionFactory【如果没有配置事务工厂,则返回托管事务工厂】,接着TransactionFactory基于DataSource或者连接来产生一个事务,接下来由Configuration生成一个包含事务的执行器Executor,最后通过configuration, executor, autoCommit来返回DefaultSqlSession。如果打开事务出错,则需要关闭它和清空错误上下文。

DefaultSqlSession提供了相关的数据库操作,对于selectOne的实现需要注意NPE的避免,在调用selectList的时候,如果得到0条则返回null,得到1条则返回1条,得到多条则报TooManyResultsException错误,所以一般建议在mapper中编写resultType的时候使用包装类型而不是基本类型,比如推荐使用Integer而不是int。把参数包装成集合的时候需要注意使用的是StrictMap,如果找不到对应的key,直接抛BindingException例外,而不是返回null。其他的相关实现大都是通过MappedStatement和Executor来实现的。对于selectMap的实现处理是例外,其实现如下代码所示:

public <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {

    list = selectList(statement, parameter, rowBounds);

    mapResultHandler = new DefaultMapResultHandler<K, V>(mapKey,

                                                               configuration.getObjectFactory(), configuration.getObjectWrapperFactory());

    context = new DefaultResultContext();

    for (Object o : list) {

      //循环用DefaultMapResultHandler处理每条记录

      context.nextResultObject(o);

      mapResultHandler.handleResult(context);

    }

    //DefaultMapResultHandler中包括所有已处理的记录,最后再返回Map

    return mapResultHandler.getMappedResults();

}

总结:MyBatis无论通过何种执行方式来处理数据的查询与修改等,其底层都是通过SqlSession来处理的。MyBatis的SqlSession的源码实现是比较简单的,其难点是在结合其管辖的四大对象来实现对应的功能。

 

猜你喜欢

转载自blog.csdn.net/lichunericli/article/details/82315734