首页 国际新闻正文
作者:皮皮哥 
大众号:Java知音


Mybatis作业原理也是面试的一大考点,有必要要对其十分明晰,这样才干怼回去。本文建立在Spring+SpringMVC+Mybatis整合的项目之上。

我将其作业原理分为六个部分:

  1. 读取中心装备文件并回来InputStream流目标。
  2. 依据InputStream流目标解分出Configuration目标,然后创立SqlSessionFactory工厂目标
  3. 依据一系列特点从SqlSessionFactory工厂中创立SqlSession
  4. 从SqlSessg2023ion中调用Executor履行数据库操作&&生成详细SQL指令
  5. 对履行成果进行二次封装
  6. 提交与业务

先给咱们看看我的实体类:

1. 读取中心装备文件

1.1 装备文件mybatis-config.xml

当然,还有许多能够在XML 文件中进行装备,上面的示例指出的则是最要害的部分。要留意 XML 头部的声明,用来验证 XML 文档正确性。environment 元素体中包括了业务管理和衔接池的装备。mappers 元素则是包括一组 mapper 映射器(这些 mapper 的 XML 文件包括了 SQL 代码和映射界说信息)。

1.2 BookMapper.xml



PUBLIC "-//mybatis.org//DTD M段晓岩apper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">



insert into book (name,number) values (#{name},#{number})


便是一个一般的mapper.xml文件。

1.3 Main办法

从 XML 文件中构建 SqlSessionFactory 的实例十分简略,主张运用类途径下的资源文件进行装备。可是也能够运用恣意的输入流(InputStream)实例,包括字符串方式的文件途径或许 file:// 的 URL 方式的文件途径来装备。

MyBatis 包括一个名叫 Resources 的东西类,它包括一些有用办法,可使从 classpath 或其他方位加载资源文件愈加简单。

这个代码是依据Mybatis官方供给的一个不运用 XML 构建 SqlSessionFactory的一个Demo改编的。

留意:是官方给的一个不运用 XML 构建 SqlSessionFactory的比如,那么咱们就从这个比如中查找进口来分析。

2. 依据装备文件生成SqlSessionFactory工厂目标

2.1 Resources.getResourceAsStream(resource);源码分析

Resources是mybatis供给的一个加载资源文件的东西类。

值的留意的是,跃泽吮血蛛它回来了一个InputStream目标。

2.2 new SqlSessionFactoryBuilder().build(inputStream);源码分析

public SqlSessionFactoryBuilder() {
}

所以new SqlSessionFactoryBuilder()仅仅创立一个目标实例,而没有目标回来(缔造者形式),目标的回来交给build()办法。

public SqlSessionFactory build(InputStream inputStream) {
return this.build((InputStream)inputStream, (String)null, (Properties)null);
}

这儿要传入一个inputStream目标,便是将咱们上一步获取到的InputStream目标传入。

怎么解析的就大约说下,通爸爸女儿过Document目标来解析,然后回来InputStream目标,然后交给XMLConfigBuilder构形成org.apache.ibatis.session.Configuration目标,然后交给build()办法结构程SqlSessionFactory:

public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
public DefaultSqlSessionFactory(Configuration config面试官:你分析过mybatis作业原理吗?uration) {
this.configuration = configuration;
}

3. 创立SqlSession

SqlSession 彻底包括了面向数据库履行 SQL 指令所需的一切办法。你能够经过 SqlSession 实例来直接履行已映射的 SQL 句子。

public SqlSession openSession() {
return this.openSessionFromDataSource(this.configuration.getDefaultExecutorType(面试官:你分析过mybatis作业原理吗?), (TransactionIsolationLevel)null, false);
}

调用自身的o鲍长义penSessionFromD荆棘婚途ataSource办法:姜仁卿

  1. getDefaultExecutorType()默许是SIMPLE。
  2. 留意TX等级是 Null, autoCommit是false。

构建过程:

Environment>>TransactionFactory+autoCommit+tx-level>>Transaction+ExecType>>Execut面试官:你分析过mybatis作业原理吗?or+Configuration+autoCommit>>SqlSession

其间,Environment是Confikayzoguration中的特点。

4. 调用Executor履行数据库操作&&生成详细SQL指令

在拿到SqlSession目标后,咱们调用它的insert办法。

public int insert(String statement, Object parameter) {
return this.update(statement, parameter);
}

它调用了自身的update(statement, parameter)办法:

mappedStatements便是咱们平常说的sql映射目标.

源码如下:

protected final Map mappedStatements;

可见它是一个Map调集,在咱们加载xml装备的时分,mapping.xml的namesp罗大发ace和id信息就会寄存为mappedStatements的key,对应的,sql句子便是对应的value.

然后调用BaseExecutor中的update办法:

public int update(MappedStatement ms, Object parameter) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing an update").object(ms.getId());
if (this.closed) {
throw new ExecutorException("Executor was closed.");
} else {
this.clearLocalCache();
// 真实做履行操作的办法
return this.doUpdate(ms, parameter);
}
}

doUpdate才是真实做履行操作的办法:

public int doUpdate(MappedStatement ms, Object parameter) throws SQLException {
Statement stmt = null;
int var6;
try {
Configuration configuration = ms.getConfiguration();
// 创立StatementHandler目标,然后创立Statement目标
StatementHandler handler = configuration.newStatementHandler(this, ms, parameter, RowBounds.DEFAULT, (ResultHandler)null, (BoundSql)null);
// 将sql句子和参数绑定并生成SQL指令
stmt = this.prepareStatement(handler, ms.getStatementLog());
var6 = handler.update(stmt);
} finally {
this.closeStatement(stmt);
}
return var6;
}

先来看看prepareStatement办法,看看mybatis是克里斯蒂马克怎么将sql拼接组成的:

private Stat开缸养水全程图文记载ement prepareState深存记ment(StatementHandler handler, Log stateme面试官:你分析过mybatis作业原理吗?ntLog) throws SQLException {
Connection connection = this.getConnection(statementLog);
// 预备Statement
Statement stmt = handler.prepare(connection);
// 设置SQL查询中的参数值
handler.parameterize(stmt);
return stmt;
}

来看看parameterize办法:

public void parameterize(Statement statement) throws SQLException {
this.parameterHandler.setParameters((PreparedStatement)statement);
}

这儿把statement转化程Prepar任鱼网选号edStatement目标,它比Statement更快更安全。

这都是咱们在JDBC中熟用的目标,就不做介绍了,所以也能看出来Mybatis是对JDBC的封装。

从ParameterMapping中读取参数值和类型,然后设置到SQL句子中:

5. 对查询成果二次封装

在doUpdate办法中,解析生成完新的SQL后,然后履行var6 = handler.update(stmt);咱们来看看它的源码。

由于咱们是刺进操作,回来的是一个int类型的值,所以这儿mybatis给咱们直接回来int。

假如是query操作,回来的是一个ResultSet,mybatis将查询成果包装程ResultSetWrapper类型,司屹川然后一步步对应java类型赋值等…有爱好的能够自己去看看。

6. 提交与业务

最终,来看看commit()办法的源码。

public void commit() {
this.commit(false);
}

调用其目标自身的commit()子洲醉汉办法:

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

假如dirty是false,则进行回滚;假如是true,则正常提交。

private boolean isCommitOr面试官:你分析过mybatis作业原理吗?RollbackRequired(boolean force) {
return !th面试官:你分析过mybatis作业原理吗?is.autoCommit && this.dirty || force;
}

调用CachingExecutor的commit办法:

public void commit(boolean required) throws SQLException {
this.delegate.commit(required);
this.tcm.commit();
}

调用BaseExecutor的commit办法:

public void commit(boolean required) 面试官:你分析过mybatis作业原理吗?throws SQLException {
if (this.closed) {
throw new Exe戒欲cutorException("Cannot commit, transaction is already closed");
} else {
this.clearLocalCache();
this.flushStatements();
if (required) {
this.transaction.commit();
}
}
}

最终调用JDBCTransaction的commit办法:

publ肉核ic void commit() throws SQLException {
if (this.connection != null && !this.connection.getAutoCommit()) {
if (log.isDebugEnabled()) {
log.debug("Committing JDBC Connection忘却你的欢欣城 [" + this.connecti重生之红星闪烁on + "]");
}
// 提交衔接
this.connection.commit();
}
}

Demo参阅文档

http://www.mybatis.org/mybatis-3/zh/getting-started.html

34张架构史上最全技术知识图谱

版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。