mybatis设计总览

目录结构:

通过配置文件,获取SqlSessionFactory

XMLConfigBuilder 解析配置文件,获取SqlSessionFactory

    private static SqlSessionFactory getSqlSessionFactory() {
String resource = "mybatis/mybatis-config.xml";
InputStream inputStream = null;
try {
inputStream = Resources.getResourceAsStream(resource);
} catch (IOException e) {
e.printStackTrace();
}
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
return sqlSessionFactory;
}

mybatis-config.xml,数据源和mapper配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<typeAliases>
<typeAlias type="entity.User" alias="User"/>
</typeAliases> <environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost/mybatisLearn"/>
<property name="username" value="mysql"/>
<property name="password" value="mysql"/>
</dataSource>
</environment>
</environments> <mappers>
<mapper resource="mapper/UserMapper.xml"/>
</mappers> </configuration>

SqlSessionFactory的属性和方法

    private final Configuration configuration;

    public SqlSession openSession() {
return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(), (TransactionIsolationLevel)null, false);
} private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null; DefaultSqlSession var8;
try {
Environment environment = this.configuration.getEnvironment();
TransactionFactory transactionFactory = this.getTransactionFactoryFromEnvironment(environment);
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
Executor executor = this.configuration.newExecutor(tx, execType);
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();
} return var8;
}

SqlSessionFactory的功能就是获取SqlSession,默认实现类DefaultSqlSession,DefaultSqlSession可以执行curd,也可以通过获取mapper来执行curd

DefaultSqlSession是直接执行sql操作数据库,mapper是通过接口方法(实际上还是要映射sql)

sqlSession可以指定事务隔离级别

TransactionIsolationLevel:

    NONE(0),
READ_COMMITTED(2),
READ_UNCOMMITTED(1),
REPEATABLE_READ(4),
SERIALIZABLE(8);

DefaultSqlSession的属性和方法

    private Configuration configuration;
private Executor executor;
private boolean autoCommit;
private boolean dirty;
private List<Cursor<?>> cursorList; public void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {
try {
MappedStatement ms = this.configuration.getMappedStatement(statement);
this.executor.query(ms, this.wrapCollection(parameter), rowBounds, handler);
} catch (Exception var9) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + var9, var9);
} finally {
ErrorContext.instance().reset();
} } public int update(String statement, Object parameter) {
int var4;
try {
this.dirty = true;
MappedStatement ms = this.configuration.getMappedStatement(statement);
var4 = this.executor.update(ms, this.wrapCollection(parameter));
} catch (Exception var8) {
throw ExceptionFactory.wrapException("Error updating database. Cause: " + var8, var8);
} finally {
ErrorContext.instance().reset();
} return var4;
} public void commit(boolean force) {
try {
this.executor.commit(this.isCommitOrRollbackRequired(force));
this.dirty = false;
} catch (Exception var6) {
throw ExceptionFactory.wrapException("Error committing transaction. Cause: " + var6, var6);
} finally {
ErrorContext.instance().reset();
} } public <T> T getMapper(Class<T> type) {
return this.configuration.getMapper(type, this);
}

Configuration是对mybatis-config.xml解析后的封装,配置文件的节点对应Configuration的属性

例如:<environment 对应 protected Environment environment;

注意Executor是在SqlSessionFactory中就获取的:Executor executor = this.configuration.newExecutor(tx, execType);

实际上调用的configuration中的方法:

    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? this.defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Object 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 (this.cacheEnabled) {
executor = new CachingExecutor((Executor)executor);
} Executor executor = (Executor)this.interceptorChain.pluginAll(executor);
return executor;
}

根据参数生成对应的executor的实现

看看抽象类BaseExecutor的方法:

    protected Transaction transaction;
protected Executor wrapper;
protected ConcurrentLinkedQueue<BaseExecutor.DeferredLoad> deferredLoads;
protected PerpetualCache localCache;
protected PerpetualCache localOutputParameterCache;
protected Configuration configuration;
protected int queryStack = 0;
private boolean closed; public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
if (this.closed) {
throw new ExecutorException("Executor was closed.");
} else {
if (this.queryStack == 0 && ms.isFlushCacheRequired()) {
this.clearLocalCache();
} List list;
try {
++this.queryStack;
list = resultHandler == null ? (List)this.localCache.getObject(key) : null;
if (list != null) {
this.handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
list = this.queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
--this.queryStack;
} if (this.queryStack == 0) {
Iterator i$ = this.deferredLoads.iterator(); while(i$.hasNext()) {
BaseExecutor.DeferredLoad deferredLoad = (BaseExecutor.DeferredLoad)i$.next();
deferredLoad.load();
} this.deferredLoads.clear();
if (this.configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
this.clearLocalCache();
}
} return list;
}
}

看看其中的SimpleExecutor:

    public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null; int var6;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, (ResultHandler)null, (BoundSql)null);
stmt = this.prepareStatement(handler, ms.getStatementLog());
var6 = handler.update(stmt);
} finally {
this.closeStatement(stmt);
} return var6;
} public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null; List var9;
try {
Configuration configuration = ms.getConfiguration();
StatementHandler handler = configuration.newStatementHandler(this.wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
stmt = this.prepareStatement(handler, ms.getStatementLog());
var9 = handler.query(stmt, resultHandler);
} finally {
this.closeStatement(stmt);
} return var9;
}

还是调用的configuration的方法

处理sql相关的类

MappedStatement,获取BoundSql

    public BoundSql getBoundSql(Object parameterObject) {
BoundSql boundSql = this.sqlSource.getBoundSql(parameterObject);
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings == null || parameterMappings.isEmpty()) {
boundSql = new BoundSql(this.configuration, boundSql.getSql(), this.parameterMap.getParameterMappings(), parameterObject);
} Iterator i$ = boundSql.getParameterMappings().iterator(); while(i$.hasNext()) {
ParameterMapping pm = (ParameterMapping)i$.next();
String rmId = pm.getResultMapId();
if (rmId != null) {
ResultMap rm = this.configuration.getResultMap(rmId);
if (rm != null) {
this.hasNestedResultMaps |= rm.hasNestedResultMaps();
}
}
} return boundSql;
}

BoundSql,获取执行的sql

    private String sql;
private List<ParameterMapping> parameterMappings;
private Object parameterObject;
private Map<String, Object> additionalParameters;
private MetaObject metaParameters;

BaseStatementHandler,获取Statement

    public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(this.boundSql.getSql());
Statement statement = null; try {
statement = this.instantiateStatement(connection);
this.setStatementTimeout(statement, transactionTimeout);
this.setFetchSize(statement);
return statement;
} catch (SQLException var5) {
this.closeStatement(statement);
throw var5;
} catch (Exception var6) {
this.closeStatement(statement);
throw new ExecutorException("Error preparing statement. Cause: " + var6, var6);
}
}

SimpleStatementHandler,获取Statement

   protected Statement instantiateStatement(Connection connection) throws SQLException {
return this.mappedStatement.getResultSetType() != null ? connection.createStatement(this.mappedStatement.getResultSetType().getValue(), 1007) : connection.createStatement();
} public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
String sql = this.boundSql.getSql();
statement.execute(sql);
return this.resultSetHandler.handleResultSets(statement);
}

最终还是JDBC的那一套。

mybatis源码笔记的更多相关文章

  1. 学习笔记02(随便看看mybatis源码)

    两个很有名的持久层hibernate和mybatis应该很熟悉不过了,两者最大相同点是底层都是对jdbc的封装,最大的不同点是前者是自动生成sql语句,后者是需要我们在映射文件中写出sql. 其实从以 ...

  2. mybatis源码分析(一)

    mybatis源码分析(sqlSessionFactory生成过程) 1. mybatis框架在现在各个IT公司的使用不用多说,这几天看了mybatis的一些源码,赶紧做个笔记. 2. 看源码从一个d ...

  3. Tomcat8源码笔记(三)Catalina加载过程

    之前介绍过 Catalina加载过程是Bootstrap的load调用的  Tomcat8源码笔记(二)Bootstrap启动 按照Catalina的load过程,大致如下: 接下来一步步分析加载过程 ...

  4. mybatis源码学习(一) 原生mybatis源码学习

    最近这一周,主要在学习mybatis相关的源码,所以记录一下吧,算是一点学习心得 个人觉得,mybatis的源码,大致可以分为两部分,一是原生的mybatis,二是和spring整合之后的mybati ...

  5. MyBatis源码分析(一)开篇

    源码学习的好处不用多说,Mybatis源码量少.逻辑简单,将写个系列文章来学习. SqlSession Mybatis的使用入口位于org.apache.ibatis.session包中的SqlSes ...

  6. MyBatis源码分析-MyBatis初始化流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  7. MyBatis源码分析-SQL语句执行的完整流程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  8. MyBatis源码分析-IDEA新建MyBatis源码工程

    MyBatis 是支持定制化 SQL.存储过程以及高级映射的优秀的持久层框架.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以对配置和原生Map使用简 ...

  9. MyBatis源码分析(5)——内置DataSource实现

    @(MyBatis)[DataSource] MyBatis源码分析(5)--内置DataSource实现 MyBatis内置了两个DataSource的实现:UnpooledDataSource,该 ...

随机推荐

  1. [LeetCode] 10. 正则表达式匹配

    题目链接:https://leetcode-cn.com/problems/regular-expression-matching/ 题目描述: 给定一个字符串 (s) 和一个字符模式 (p).实现支 ...

  2. python 获取秒级时间间隔

    import datetime,time start_tm=datetime.datetime.now() time.sleep() end_tm=datetime.datetime.now() pr ...

  3. 嵌入式操作系统---打印函数(printf/sprintf)的实现

    一.打印函数简介 作用:将“给定的内容”按照“指定的格式”输出到“指定目标内”. 打印函数的基本格式: char print_buf[BUF_SIZE]; void printf(const char ...

  4. 点击button自动刷新页面的奇葩错误

    以前在写练习的时候遇到过这样一个问题,自己在html中写了一个button <button>test1</button> 在没有给其附上onclick事件时是点击是不会有任何反 ...

  5. [Oracle]Sqlplus 中使用 new_value

    通过再sqlplus 中使用 new_value,可以把从表中查询出来的值,放置到 变量中.然后使用变量时,类似与宏定义一样,就可以像使用表中字段一样方便. 这使得sqlplus 的脚本具备和pl/s ...

  6. 三种dedecms友情链接调用标签

    三种dedecms友情链接调用标签: 1.获取友情链接分类 {dede:flinktype}<span>[field:typename/]</span>{/dede:flink ...

  7. Messenger更改系统语言以后无法登陆,提示“初始设置被修改”

    在安装messenger机器上使用SQL management studio打开数据库,链接YCD的数据库,找到dbo.Dic_Defaults的表,编辑打开以后找到“CultureInfo”两项,删 ...

  8. c语言提高(第二次作业)

    1. 画出字符串一级指针内存四区模型 #include <stdio.h> #include <string.h> int main(void) { char buf[20]= ...

  9. [模板] 匈牙利算法&&二分图最小字典序匹配

    匈牙利算法 简介 匈牙利算法是一种求二分图最大匹配的算法. 时间复杂度: 邻接表/前向星: \(O(n * m)\), 邻接矩阵: \(O(n^3)\). 空间复杂度: 邻接表/前向星: \(O(n ...

  10. [SimplePlayer] 7. 多线程处理

    在前面的文章中,我们分别实现了视频图像解码.播放,音频解码.播放,现在则需要把这些功能组合起来.总体上来说,整个程序的功能可以分为两条线路:视频以及音频,两条线之间除了后续的同步操作之外基本没有任何关 ...