Mybatis源码探索之SqlSession
SqlSessionFactory
SqlSessionFactory使用了工厂模式创建SqlSession的,它的默认实现类是DefaultSqlSessionFactory。方法
它共有以下几个方法:publicinterfaceSqlSessionFactory{SqlSessionopenSession();SqlSessionopenSession(booleanautoCommit);SqlSessionopenSession(Connectionconnection);SqlSessionopenSession(TransactionIsolationLevellevel);SqlSessionopenSession(ExecutorTypeexecType);SqlSessionopenSession(ExecutorTypeexecType,booleanautoCommit);SqlSessionopenSession(ExecutorTypeexecType,TransactionIsolationLevellevel);SqlSessionopenSession(ExecutorTypeexecType,Connectionconnection);ConfigurationgetConfiguration();}复制代码
可以根据参数的不同创建不同特性的SqlSession,具体实现可以参考DefaultSqlSessionFactory源码DefaultSqlSessionFactory
它的核心方法是openSessionFromDataSource(ExecutorTypeexecType,TransactionIsolationLevellevel,booleanautoCommit),从数据源中获取SqlSession。privateSqlSessionopenSessionFromDataSource(ExecutorTypeexecType,TransactionIsolationLevellevel,booleanautoCommit){Transactiontxnull;try{finalEnvironmentenvironmentconfiguration。getEnvironment();获取事务工厂,默认是ManagedTransactionFactoryfinalTransactionFactorytransactionFactorygetTransactionFactoryFromEnvironment(environment);txtransactionFactory。newTransaction(environment。getDataSource(),level,autoCommit);获取执行器,默认是SimpleExecutorfinalExecutorexecutorconfiguration。newExecutor(tx,execType);returnnewDefaultSqlSession(configuration,executor,autoCommit);}catch(Exceptione){closeTransaction(tx);mayhavefetchedaconnectionsoletscallclose()throwExceptionFactory。wrapException(Erroropeningsession。Cause:e,e);}finally{ErrorContext。instance()。reset();}}复制代码
常用的方法是openSession(),但是调用的还是核心方法。通过无参的openSession()方法创建SqlSession时,事务默认不自动提交,事务隔离级别null,默认执行器类型是ExecutorType。REUSEOverridepublicSqlSessionopenSession(){returnopenSessionFromDataSource(configuration。getDefaultExecutorType(),null,false);}复制代码SqlSession
SqlSession是MyBaits对外提供的最关键的核心接口,通过它可以执行数据库读写命令、获取映射器、管理事务等;SqlSession也意味着客户端与数据库的一次连接,客户端对数据库的访问请求都是由SqlSession来处理的,SqlSession由SqlSessionFactory创建,每个SqlSession都会引用SqlSessionFactory中全局唯一单例存在的configuration对象。SqlSession的默认实现类是DefaultSqlSession方法
SqlSession的方法主要分为以下6类:
1、SQL语句执行方法
2、立即批量更新方法
3、事务控制方法
4、本地缓存
5、映射器获取
6、SqlSession关闭
对应的主要方法如下:
SqlSession的方法中参数statement,都是Mapper接口中的方法的全限定名,例如:mapperClasses。UserInfoMapper。selectByPrimaryKey。
1、SQL语句执行方法intdelete(Stringstatement,Objectparameter);intinsert(Stringstatement,Objectparameter);intupdate(Stringstatement,Objectparameter);voidselect(Stringstatement,Objectparameter,RowBoundsrowBounds,ResultHandlerhandler);TTselectOne(Stringstatement,Objectparameter);K,VMapK,VselectMap(Stringstatement,Objectparameter,StringmapKey,RowBoundsrowBounds);EListEselectList(Stringstatement,Objectparameter,RowBoundsrowBounds,ResultHandlerhandler);TCursorTselectCursor(Stringstatement,Objectparameter,RowBoundsrowBounds);复制代码
delete、insert方法最终调用的还是update方法,update源码如下:publicintupdate(Stringstatement,Objectparameter){try{dirtytrue;获取MappedStatementMappedStatementmsconfiguration。getMappedStatement(statement);returnexecutor。update(ms,wrapCollection(parameter));}catch(Exceptione){throwExceptionFactory。wrapException(Errorupdatingdatabase。Cause:e,e);}finally{ErrorContext。instance()。reset();}}复制代码
select、selectOne最终调用的是selectList方法,selectMap方法也是通过selectList方法查询到结果的,只不过再查询之后又转换成了map对象。selectList方法源码如下:privateEListEselectList(Stringstatement,Objectparameter,RowBoundsrowBounds,ResultHandlerhandler){try{MappedStatementmsconfiguration。getMappedStatement(statement);returnexecutor。query(ms,wrapCollection(parameter),rowBounds,handler);}catch(Exceptione){throwExceptionFactory。wrapException(Errorqueryingdatabase。Cause:e,e);}finally{ErrorContext。instance()。reset();}}复制代码
selectOne源码:查询结果集如果是一个就取这个,多个则抛异常publicTTselectOne(Stringstatement,Objectparameter){Popularvotewastoreturnnullon0resultsandthrowexceptionontoomany。ListTlistthis。selectList(statement,parameter);if(list。size()1){returnlist。get(0);}elseif(list。size()1){thrownewTooManyResultsException(Expectedoneresult(ornull)tobereturnedbyselectOne(),butfound:list。size());}else{returnnull;}}复制代码
selectCursor提供了与List相同的结果,只是它使用迭代器惰性地获取数据。selectCursor应该很少使用(应该吧,至少我没有用过)publicTCursorTselectCursor(Stringstatement,Objectparameter,RowBoundsrowBounds){try{MappedStatementmsconfiguration。getMappedStatement(statement);CursorTcursorexecutor。queryCursor(ms,wrapCollection(parameter),rowBounds);registerCursor(cursor);returncursor;}catch(Exceptione){throwExceptionFactory。wrapException(Errorqueryingdatabase。Cause:e,e);}finally{ErrorContext。instance()。reset();}}复制代码
2、立即批量更新方法
只有这个方法:
可以使用这个方法清除(执行)缓存在JDBC驱动类中的批量更新语句。ListflushStatements();publicListBatchResultflushStatements(){try{returnexecutor。flushStatements();}catch(Exceptione){throwExceptionFactory。wrapException(Errorflushingstatements。Cause:e,e);}finally{ErrorContext。instance()。reset();}}复制代码
3、事务控制方法刷新缓存在JDBC驱动类中的批量语句并提交数据库连接,如果数据库连接没有updatesdeletesinserts被调用则不会提交voidcommit();commit()升级版,可以根据参数来决定是否强制提交voidcommit(booleanforce);丢弃挂起的批处理语句并回滚数据库连接,如果数据库连接没有updatesdeletesinserts被调用则不会回滚voidrollback();rollback()的升级版,可以根据参数来决定是否强制回滚voidrollback(booleanforce);复制代码
4、本地缓存清空本地缓存,只是清空本地缓存,跟二级缓存没关系voidclearCache();复制代码
5、映射器获取从configuration对象中的mapperRegistry(mapper注册表)中获取对应的mapper对象publicTTgetMapper(ClassTtype){returnconfiguration。getMapper(type,this);}复制代码
6、SqlSession关闭方法关闭session会话voidclose();复制代码举个栗子publicclassUserTest{privatefinalstaticSqlSessionFactorysqlSessionFactory;static{Stringresourcemybatisconfig。xml;Readerreadernull;try{readerResources。getResourceAsReader(resource);}catch(IOExceptione){System。out。println(e。getMessage());}sqlSessionFactorynewSqlSessionFactoryBuilder()。build(reader);}Testpublicvoidtest(){SqlSessionsqlSessionsqlSessionFactory。openSession();UserInfoMappermappersqlSession。getMapper(UserInfoMapper。class);UserInfouserInfossqlSession。selectOne(mapperClasses。UserInfoMapper。selectByPrimaryKey,1L);System。out。println(userInfos);UserInfouserInfomapper。selectByPrimaryKey(4L);System。out。println(userInfo);}}复制代码
使用mybatis进行crud有两种方式:
1、通过sqlSession提供的操作进行crud,这种是最原始的使用方式。这种方式可读性、可维护性都很差,一般很少使用。UserInfouserInfossqlSession。selectOne(mapperClasses。UserInfoMapper。selectByPrimaryKey,1L);复制代码
2、通过mapper进行crud,最终调用的还是第一种的方式。这种方式是ibatis被谷歌收购后,谷歌进行升级的UserInfoMappermappersqlSession。getMapper(UserInfoMapper。class);UserInfouserInfomapper。selectByPrimaryKey(4L);复制代码
能力有限,水平一般,如有错误,请多指出。
来源:https:juejin。cnpost7130802331347582990