mybatis源码阅读(一):SqlSession和SqlSessionFactory

转载自  mybatis源码阅读(一):SqlSession和SqlSessionFactory 

一、接口定义

    听名字就知道这里使用了工厂方法模式,SqlSessionFactory负责创建SqlSession对象。其中开发人员最常用的就是DefaultSqlSession

(1)SqlSession接口定义

public interface SqlSession extends Closeable {// 泛型方法,参数表示使用的查询SQL语句,返回值为查询的结果对象<T> T selectOne(String statement);// 第二个参数表示需要用户传入的实参,也就是SQL语句绑定的实参<T> T selectOne(String statement, Object parameter);// 查询结果集有多条记录,会封装成结果对象列表返回<E> List<E> selectList(String statement);<E> List<E> selectList(String statement, Object parameter);// 第三个参数用于限制解析结果集的范围<E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);/****  selectMap 方法的原理和参数都与selectList方法类型,但结果集会被映射成Map对象返回*  其中mapKey参数指定了结果集哪一列作为map的key,其他参数同上*/<K, V> Map<K, V> selectMap(String statement, String mapKey);<K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);<K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);// 返回值是游标对象,参数同上<T> Cursor<T> selectCursor(String statement);<T> Cursor<T> selectCursor(String statement, Object parameter);<T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds);// 查询的结果对象将由此处指定的handler对象处理,其余参数同上void select(String statement, Object parameter, ResultHandler handler);void select(String statement, ResultHandler handler);void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);// 执行insert语句int insert(String statement);int insert(String statement, Object parameter);// 执行update语句int update(String statement);int update(String statement, Object parameter);// 执行deleteint delete(String statement);int delete(String statement, Object parameter);// 提交事务void commit();void commit(boolean force);// 事务回滚void rollback();void rollback(boolean force);// 将请求刷新到数据库List<BatchResult> flushStatements();// 关闭当前session@Overridevoid close();// 清空session 缓存void clearCache();// 获取Configuration 对象Configuration getConfiguration();// 获取type 对象的Mapper对象<T> T getMapper(Class<T> type);// 获取该Sqlsession 对象的数据库连接Connection getConnection();
}

SqlSession数据库的C、R、U、D及事务处理接口,你懂的。

(2)SqlSessionFactory

public interface SqlSessionFactory {SqlSession openSession();SqlSession openSession(boolean autoCommit);SqlSession openSession(Connection connection);SqlSession openSession(TransactionIsolationLevel level);SqlSession openSession(ExecutorType execType);SqlSession openSession(ExecutorType execType, boolean autoCommit);SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);SqlSession openSession(ExecutorType execType, Connection connection);Configuration getConfiguration();
}

这个大家也都懂的

SqlSession实现类:DefaultSqlSession和SqlSessionManager

SqlSessionFactory实现类:DefaultSqlSessionFactory和SqlSessionManager

(3)DefaultSqlSession

@Override
public int update(String statement, Object parameter) {try {dirty = true;MappedStatement ms = configuration.getMappedStatement(statement);return executor.update(ms, wrapCollection(parameter));} catch (Exception e) {throw ExceptionFactory.wrapException("Error updating database.  Cause: " + e, e);} finally {ErrorContext.instance().reset();}
}
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {try {MappedStatement ms = configuration.getMappedStatement(statement);return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);} catch (Exception e) {throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);} finally {ErrorContext.instance().reset();}
}

这里主要看这两个方法,因为delete和insert最终执行掉用的都是update方法,查询就更不用说了。从代码上看都是从configuration对象中获取MappedStatement 对象 然后把事情交给小弟Executor去执行,这里用了很典型的策略设计模式,这个关于Executor 后面介绍。

(4)DefaultSqlSessionFactory

/*** 通过数据源获取数据库连接,并创建Executor以及DefaultSqlSession对象*/
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {Transaction tx = null;try {final Environment environment = configuration.getEnvironment();final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);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();}
}/***  用户提供数据库连接对象,使用该数据库连接对象创建Executor和DefaultSqlSession对象*/
private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) {try {boolean autoCommit;try {autoCommit = connection.getAutoCommit();} catch (SQLException e) {// Failover to true, as most poor drivers// or databases won't support transactionsautoCommit = true;}      final Environment environment = configuration.getEnvironment();final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);final Transaction tx = transactionFactory.newTransaction(connection);final Executor executor = configuration.newExecutor(tx, execType);return new DefaultSqlSession(configuration, executor, autoCommit);} catch (Exception e) {throw ExceptionFactory.wrapException("Error opening session.  Cause: " + e, e);} finally {ErrorContext.instance().reset();}
}

DefaultSqlSessionFactory主要提供了两种创建DefaultSqlSession对象的方式,一种是通过数据源获取数据库连接,并创建Executor以及DefaultSqlSession对象,另一种是用户提供数据库连接对象,使用该数据库连接对象创建Executor和DefaultSqlSession对象。

(5)SqlSessionManager

SqlSessionManager同时实现SqlSession接口和SqlSessionFactory接口,也就是同时提供了创建SqlSession对象以及SqlSession对象操作数据库的功能。SqlSessionManager与DefaultSqlSessionFactory的主要不同点是SqlSessionManager提供了两种模式,一种是和DefaultSqlSessionFactory的行为相同,同一线程每次访问数据库就都会创建新的DefaultSqlSession,第二种是通过ThreadLocal变量记录当前线程的SqlSession对象,避免同一线程多次创建SqlSession对象。至于使用动态代理的目的,是为了通过拦截器InvocationHandler,增强目标target的方法调用。

private final SqlSessionFactory sqlSessionFactory;
// SqlSession的代理对象 会使用JDK的动态代理方式实现
private final SqlSession sqlSessionProxy;/*** ThreadLocal 变量,记录一个与当前线程绑定的SqlSession对象* localSqlSession 中记录的SqlSession对象的代理对象,在SqlSessionManager初始化的时候*/
private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<SqlSession>();
/*** SqlSessionManager 的私有构造方法*/
private SqlSessionManager(SqlSessionFactory sqlSessionFactory) {this.sqlSessionFactory = sqlSessionFactory;// 使用动态代理生成SqlSession的代理对象this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance(SqlSessionFactory.class.getClassLoader(),new Class[]{SqlSession.class},new SqlSessionInterceptor());
}/*** 通过newInstance方法创建SqlSessionManager对象* @param reader* @return*/public static SqlSessionManager newInstance(Reader reader) {return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, null));}
// 内部类
private class SqlSessionInterceptor implements InvocationHandler {public SqlSessionInterceptor() {// Prevent Synthetic Access}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 获取当前线程绑定的SqlSession对象final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get();if (sqlSession != null) {// 第二种模式try {return method.invoke(sqlSession, args);} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable(t);}} else {// 第一种模式 创建新的SqlSessionfinal SqlSession autoSqlSession = openSession();try {final Object result = method.invoke(autoSqlSession, args);autoSqlSession.commit();return result;} catch (Throwable t) {autoSqlSession.rollback();throw ExceptionUtil.unwrapThrowable(t);} finally {autoSqlSession.close();}}}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/322759.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源纯C#工控网关+组态软件(六)图元组件

一、 图元概述 图元是构成人机界面的基本单元。如一个个的电机、设备、数据显示、仪表盘&#xff0c;都是图元。构建人机界面的过程就是铺排、挪移、定位图元的过程。 图元设计是绘图和编码的结合。因为图元不仅有显示和动画&#xff0c;还有背后操纵动画的控制逻辑。 一个好…

git合并分支的策略(赞)

假设当前有两个分支 master和test&#xff0c;两个分支一模一样&#xff0c;都有这三个文件 现在test添加一个test4.txt&#xff0c;然后提交到本地&#xff08;git add . git commit&#xff09; 切换到master分支上&#xff0c;git checkout master git merge test 这样mase…

改造独立部署(SCD)模式下.NET Core应用程序 dotnet的exe文件启动过程

设置一个小目标 改造前 改造后 独立部署SCD模式&#xff0c;是指在使用dotnet publish 命令时带上-r 参数运行时标识符&#xff08;RID&#xff09;。 目标提出原因&#xff1a;SCD模式下文件太乱了&#xff0c;很多文件在开发时大多又涉及不到&#xff0c;发布后如果能把文件…

mybatis源码阅读(四):mapper(dao)实例化

转载自 mybatis源码阅读(四)&#xff1a;mapper(dao)实例化 在开始分析之前&#xff0c;先来了解一下这个模块中的核心组件之间的关系&#xff0c;如图&#xff1a; 1.MapperRegistry&MapperProxyFactory MapperRegistry是Mapper接口及其对应的代理对象工程的注册中心&…

自定义路由匹配和生成

前言 前两篇文章主要总结了CMS系统两个技术点在ASP.NET Core中的应用&#xff1a; 《ASP.NET Core 中的SEO优化&#xff08;1&#xff09;&#xff1a;中间件实现服务端静态化缓存》 《ASP.NET Core 中的SEO优化&#xff08;2&#xff09;&#xff1a;中间件中渲染Razor视图》…

如何封装并发布一个属于自己的ui组件库

以前就一直有个想法自己能不能封装一个类似于elementui一样的组件库&#xff0c;然后发布到npm上去&#xff0c;毕竟前端说白了&#xff0c;将组件v上去&#xff0c;然后进行数据交互。借助这次端午&#xff0c;终于有机会&#xff0c;尝试自己去封装发布组件库了 我这里了只做…

听云支持.NET Core的应用性能监控

随着微软于2017年8月正式发布.NET Core 2.0&#xff0c; .NET Core 社区开始活跃&#xff0c;众多.NET开发者开始向跨平台转变。 听云于2017年11月推出了.NET Core应用监控工具&#xff0c;和听云其他语言的监控工具一样&#xff0c;.NET Core应用监控工具具有以下特征&#xf…

mybatis源码阅读(五) ---执行器Executor

转载自 mybatis源码阅读(五) ---执行器Executor 1. Executor接口设计与类结构图 public interface Executor {ResultHandler NO_RESULT_HANDLER null;// 执行update&#xff0c;delete&#xff0c;insert三种类型的sql语句int update(MappedStatement ms, Object parameter…

[52ABP实战系列] .NET CORE实战入门第三章更新了

早安 各位道友好&#xff0c;.NET CORE入门视频的第三章也算录制完毕了。欢迎大家上传课网进行学习。 更新速度 大家也知道最近的社会新闻比较多。频繁发生404、关键字打不出来&#xff0c;我个人也在关注这些事件。导致精力分散&#xff0c;没有做到稳定更新&#xff0c;现在呢…

如何安装nuxt

因为vue是单页面应用&#xff0c;所以不被Seo&#xff0c;如百度和Google抓取到&#xff0c;在Vue中如果想要爬虫爬到就必须使用nuxt 那么如何安装使用呢&#xff1f; yarn create nuxt-app <project-name> cd <project-name> yarn build yarn start必须先build&a…

mybatis源码阅读(六) ---StatementHandler了解一下

转载自 mybatis源码阅读(六) ---StatementHandler了解一下 StatementHandler类结构图与接口设计 BaseStatementHandler&#xff1a;一个抽象类&#xff0c;只是实现了一些不涉及具体操作的方法 RoutingStatementHandler&#xff1a;类似路由器&#xff0c;根据配置文件来路由…

基于OIDC(OpenID Connect)的SSO(纯JS客户端)

在上一篇基于OIDC的SSO的中涉及到了4个Web站点&#xff1a; oidc-server.dev&#xff1a;利用oidc实现的统一认证和授权中心&#xff0c;SSO站点。 oidc-client-hybrid.dev&#xff1a;oidc的一个客户端&#xff0c;采用hybrid模式。 oidc-client-implicit.dev&#xff1a;od…

IIS中的 Asp.Net Core 和 dotnet watch

在基于传统的.NET Framework的Asp.Net Mvc的时候&#xff0c;本地开发环境中可以在IIS中建立一个站点&#xff0c;可以直接把站点的目录指向asp.net mvc的项目的根目录。然后build一下就可以在浏览器里面刷新到最新的修改了&#xff0c;也可以附加到w3wp的进程进行调试。但是在…

foreach方法使用

用法 foreach方法主要是针对数组而言的&#xff0c;对数组中的每个元素可以执行一次方法 var array [a, b, c, e]; array.forEach((a)> {console.log(a); });属性 foreach方法主要有三个参数&#xff0c;分别是数组内容、数组索引、整个数组 var array [a, b, c, e]; arra…

.NET Core 控制台程序读 appsettings.json 、注依赖、配日志、设 IOptions

.NET Core 控制台程序没有 ASP.NET Core 的 IWebHostBuilder 与 Startup.cs &#xff0c;那要读 appsettings.json、注依赖、配日志、设 IOptions 该怎么办呢&#xff1f;因为这些操作与 ASP.NET Core 无依赖&#xff0c;所以可以自己动手&#xff0c;轻松搞定。 1、读 appsett…

Object.keys方法拿到对象的key值

项目中的高级搜索选项用到了Object.keys方法&#xff0c; 那么它是用来干嘛的呢&#xff1a;删除某个子对象里的数据 var anObj { aaa: kejin,bbb: shenxian,ccc: yuanshan };let params {...anObj,ddd: luanwu } console.log(params) console.log(Object.keys(anObj)); // …

jsdiff 比较文本内容差异

翻译自 jsdiff JavaScript文本内容差异实现。 基于"An O(ND) Difference Algorithm and its Variations" (Myers, 1986) 中提出的算法 。 安装 npm install diff --save API Diff.diffChars(oldStr, newStr[, options]) -区分两个文本块&#xff0c;逐字符比较。…

Net Core下多种ORM框架特性及性能对比

在.NET Framework下有许多ORM框架&#xff0c;最著名的无外乎是Entity Framework&#xff0c;它拥有悠久的历史以及便捷的语法&#xff0c;在占有率上一路领先。但随着Dapper的出现&#xff0c;它的地位受到了威胁&#xff0c;本文对比了在.NET Core下 两种框架的表现以及与原生…

从ThoughtWorks 2017技术雷达看微软技术

ThoughtWorks在每年都会出品两期技术雷达&#xff0c;这是一份关于技术趋势的报告&#xff0c;它比起一些我们能在市面上见到的其他各种技术行情和预测报告&#xff0c;更加具体&#xff0c;更具可操作性&#xff0c;因为它不仅涉及到新技术大趋势&#xff0c;比如云平台和大数…

Spark入门(一)单主standalone安装

一、集群安装条件前置 实验spark安装在【Hadoop入门&#xff08;二&#xff09;集群安装】机器上&#xff0c; 已完成安装jdk,hadoop和ssh、网络等配置环境等。 spark所依赖的虚拟机和操作系统配置 环境&#xff1a;ubuntu14 spark-2.4.4-bin-hadoop2.6jdk1.8ssh 虚拟机&a…