摘要:配置测试描述测试类技术部查询表至此初步配置完成执行过程获取解析成接收方法方法方法属性定位方法数据绑定到具体方法提交传输获取配置解析标签对象获取过程源码使用
MyBatis 配置
</>复制代码
4.0.0
com.huifer
mybatisBook
1.0-SNAPSHOT
UTF-8
UTF-8
1.8
org.mybatis
mybatis
3.5.0
mysql
mysql-connector-java
8.0.13
org.projectlombok
lombok
1.18.4
true
org.apache.maven.plugins
maven-compiler-plugin
1.8
1.8
mybatis-config.xml
测试</>复制代码
DeptMapper.xml
</>复制代码
INSERT INTO dept (dname, loc)
VALUES (#{dname} , #{loc});
Dept.java
</>复制代码
package com.huifer.mybatis;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 描述:
*
* @author huifer
* @date 2019-02-21
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Dept {
private Long id;
private String dname;
private String loc;
}
测试类
</>复制代码
public class Demo {
public static void main(String[] args) throws Exception {
Dept dept = new Dept();
dept.setDname("技术部");
dept.setLoc("oc");
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(is);
SqlSession session = factory.openSession();
session.insert("insertDept", dept);
session.commit();
session.close();
}
}
查询表
至此初步配置完成
执行过程</>复制代码
graph TD
start[获取mybatis.config.xml] --> conditionA[SqlSessionFactory]
conditionA --> |xml 解析成 org.apache.ibatis.session.Configuration | conditionB[接收SqlSessionFactory]
conditionB --> |org.apache.ibatis.session.defaults.DefaultSqlSessionFactory.openSessionFromDataSource| conditionC[ SqlSession]
conditionC --> |org.apache.ibatis.session.defaults.DefaultSqlSession insert方法 update方法| conditionD[insert方法]
conditionD --> | org.apache.ibatis.mapping.MappedStatement sqlSource属性 | conditionE[mapper 定位]
conditionE --> | org.apache.ibatis.executor.SimpleExecutor doUpdate方法 stmt|conditionF[数据绑定到具体sql]
conditionF --> |org.apache.ibatis.executor.statement.PreparedStatementHandler update方法 提交| conditionG[传输sql]
conditionG -->|commit| stop
session
获取mybatils-config.xml 配置 解析xml标签
org.apache.ibatis.session.defaults.DefaultSqlSessionFactory
</>复制代码
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;
}
insert
org.apache.ibatis.session.defaults.DefaultSqlSession
</>复制代码
public int insert(String statement, Object parameter) {
return this.update(statement, parameter);
}
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;
}
ms 对象
doUpdateorg.apache.ibatis.executor.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;
}
update
</>复制代码
org.apache.ibatis.executor.statement.PreparedStatementHandler
</>复制代码
public int update(Statement statement) throws SQLException {
PreparedStatement ps = (PreparedStatement)statement;
ps.execute();
int rows = ps.getUpdateCount();
Object parameterObject = this.boundSql.getParameterObject();
KeyGenerator keyGenerator = this.mappedStatement.getKeyGenerator();
keyGenerator.processAfter(this.executor, this.mappedStatement, ps, parameterObject);
return rows;
}
Mapper
获取过程源码</>复制代码
org.apache.ibatis.builder.xml.XMLConfigBuilder 使用parseConfiguration 方法将 mybatis-config.xml 中的mappers 标签内容获取到 mapperElement具体执行获取内容 ,作用将mappers添加到configuration 中
</>复制代码
private void parseConfiguration(XNode root) {
try {
this.propertiesElement(root.evalNode("properties"));
Properties settings = this.settingsAsProperties(root.evalNode("settings"));
this.loadCustomVfs(settings);
this.loadCustomLogImpl(settings);
this.typeAliasesElement(root.evalNode("typeAliases"));
this.pluginElement(root.evalNode("plugins"));
this.objectFactoryElement(root.evalNode("objectFactory"));
this.objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
this.reflectorFactoryElement(root.evalNode("reflectorFactory"));
this.settingsElement(settings);
this.environmentsElement(root.evalNode("environments"));
this.databaseIdProviderElement(root.evalNode("databaseIdProvider"));
this.typeHandlerElement(root.evalNode("typeHandlers"));
this.mapperElement(root.evalNode("mappers"));
} catch (Exception var3) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + var3, var3);
}
}
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
Iterator var2 = parent.getChildren().iterator();
while(true) {
while(var2.hasNext()) {
XNode child = (XNode)var2.next();
String resource;
if ("package".equals(child.getName())) {
resource = child.getStringAttribute("name");
this.configuration.addMappers(resource);
} else {
resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
XMLMapperBuilder mapperParser;
InputStream inputStream;
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
inputStream = Resources.getResourceAsStream(resource);
mapperParser = new XMLMapperBuilder(inputStream, this.configuration, resource, this.configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
inputStream = Resources.getUrlAsStream(url);
mapperParser = new XMLMapperBuilder(inputStream, this.configuration, url, this.configuration.getSqlFragments());
mapperParser.parse();
} else {
if (resource != null || url != null || mapperClass == null) {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
Class mapperInterface = Resources.classForName(mapperClass);
this.configuration.addMapper(mapperInterface);
}
}
}
return;
}
}
}
当前Configuration 下的mappedStatements 属性
org.apache.ibatis.binding.MapperRegistry addMapper 方法,作用将解析到的接口对象放到configuration 中 ,一个接口只能注册一次
</>复制代码
public void addMapper(Class type) {
if (type.isInterface()) {
if (this.hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
this.knownMappers.put(type, new MapperProxyFactory(type));
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(this.config, type);
parser.parse();
loadCompleted = true;
} finally {
if (!loadCompleted) {
this.knownMappers.remove(type);
}
}
}
}
org.apache.ibatis.builder.annotation.MapperAnnotationBuilder parse方法
loadXmlResource 来确认加载具体的xml文件
</>复制代码
public void parse() {
String resource = this.type.toString();
if (!this.configuration.isResourceLoaded(resource)) {
this.loadXmlResource();
this.configuration.addLoadedResource(resource);
this.assistant.setCurrentNamespace(this.type.getName());
this.parseCache();
this.parseCacheRef();
Method[] methods = this.type.getMethods();
Method[] var3 = methods;
int var4 = methods.length;
for(int var5 = 0; var5 < var4; ++var5) {
Method method = var3[var5];
try {
if (!method.isBridge()) {
this.parseStatement(method);
}
} catch (IncompleteElementException var8) {
this.configuration.addIncompleteMethod(new MethodResolver(this, method));
}
}
}
this.parsePendingMethods();
}
private void loadXmlResource() {
if (!this.configuration.isResourceLoaded("namespace:" + this.type.getName())) {
String xmlResource = this.type.getName().replace(".", "/") + ".xml";
InputStream inputStream = this.type.getResourceAsStream("/" + xmlResource);
if (inputStream == null) {
try {
inputStream = Resources.getResourceAsStream(this.type.getClassLoader(), xmlResource);
} catch (IOException var4) {
}
}
if (inputStream != null) {
XMLMapperBuilder xmlParser = new XMLMapperBuilder(inputStream, this.assistant.getConfiguration(), xmlResource, this.configuration.getSqlFragments(), this.type.getName());
xmlParser.parse();
}
}
}
根据 loadXmlResource 中下面这行得知 , PojoMapper.xml 要和 PojoMapperInterface 放在一个路径下
</>复制代码
String xmlResource = this.type.getName().replace(".", "/") + ".xml";
具体sql
org.apache.ibatis.builder.xml.XMLStatementBuilder parseStatementNode 方法解析sql语句
</>复制代码
</>复制代码
public void parseStatementNode() {
String id = this.context.getStringAttribute("id");
String databaseId = this.context.getStringAttribute("databaseId");
if (this.databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
Integer fetchSize = this.context.getIntAttribute("fetchSize");
Integer timeout = this.context.getIntAttribute("timeout");
String parameterMap = this.context.getStringAttribute("parameterMap");
String parameterType = this.context.getStringAttribute("parameterType");
Class parameterTypeClass = this.resolveClass(parameterType);
String resultMap = this.context.getStringAttribute("resultMap");
String resultType = this.context.getStringAttribute("resultType");
String lang = this.context.getStringAttribute("lang");
LanguageDriver langDriver = this.getLanguageDriver(lang);
Class resultTypeClass = this.resolveClass(resultType);
String resultSetType = this.context.getStringAttribute("resultSetType");
StatementType statementType = StatementType.valueOf(this.context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
ResultSetType resultSetTypeEnum = this.resolveResultSetType(resultSetType);
String nodeName = this.context.getNode().getNodeName();
SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
boolean flushCache = this.context.getBooleanAttribute("flushCache", !isSelect);
boolean useCache = this.context.getBooleanAttribute("useCache", isSelect);
boolean resultOrdered = this.context.getBooleanAttribute("resultOrdered", false);
XMLIncludeTransformer includeParser = new XMLIncludeTransformer(this.configuration, this.builderAssistant);
includeParser.applyIncludes(this.context.getNode());
this.processSelectKeyNodes(id, parameterTypeClass, langDriver);
SqlSource sqlSource = langDriver.createSqlSource(this.configuration, this.context, parameterTypeClass);
String resultSets = this.context.getStringAttribute("resultSets");
String keyProperty = this.context.getStringAttribute("keyProperty");
String keyColumn = this.context.getStringAttribute("keyColumn");
String keyStatementId = id + "!selectKey";
keyStatementId = this.builderAssistant.applyCurrentNamespace(keyStatementId, true);
Object keyGenerator;
if (this.configuration.hasKeyGenerator(keyStatementId)) {
keyGenerator = this.configuration.getKeyGenerator(keyStatementId);
} else {
keyGenerator = this.context.getBooleanAttribute("useGeneratedKeys", this.configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType)) ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
}
this.builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType, fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass, resultSetTypeEnum, flushCache, useCache, resultOrdered, (KeyGenerator)keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}
}
还原sql方法
</>复制代码
SqlSource sqlSource = langDriver.createSqlSource(this.configuration, this.context, parameterTypeClass);
org.apache.ibatis.scripting.defaults.RawSqlSource RawSqlSource方法
</>复制代码
public RawSqlSource(Configuration configuration, String sql, Class parameterType) {
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class clazz = parameterType == null ? Object.class : parameterType;
this.sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap());
}
org.apache.ibatis.builder.SqlSourceBuilder parse方法还原成sql语句
</>复制代码
public SqlSource parse(String originalSql, Class parameterType, Map additionalParameters) {
SqlSourceBuilder.ParameterMappingTokenHandler handler = new SqlSourceBuilder.ParameterMappingTokenHandler(this.configuration, parameterType, additionalParameters);
GenericTokenParser parser = new GenericTokenParser("#{", "}", handler);
String sql = parser.parse(originalSql);
return new StaticSqlSource(this.configuration, sql, handler.getParameterMappings());
}
最后看一下 sqlSource
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/73404.html
摘要:源码仓库本文仓库三层结构表现层模型业务层持久层工作流程用户前端控制器用户发送请求前端控制器后端控制器根据用户请求查询具体控制器后端控制器前端控制器处理后结果前端控制器视图视图渲染视图前端控制器返回视图前端控制器用户响应结 SpringMvc 【源码仓库】【本文仓库】 三层结构 表现层 MVC模型 业务层 service 持久层 dao 工作流程 用户->前端控制器:用户...
摘要:一个写着玩的客户端,代码不复杂,轻松了解比特币。项目地址起因看书确实是很好的学习比特币的方法,但是没有代码的帮助,理解比特币如何实现时,很是困难。后来发现一个用写的完整客户端,就决定用它来研究比特币源码了,帮助我理解比特币。 一个写着玩的 bitcoin 客户端,代码不复杂,轻松了解比特币。项目地址:https://github.com/jiangleo/b... 起因 看书确实是很好...
摘要:一个写着玩的客户端,代码不复杂,轻松了解比特币。项目地址起因看书确实是很好的学习比特币的方法,但是没有代码的帮助,理解比特币如何实现时,很是困难。后来发现一个用写的完整客户端,就决定用它来研究比特币源码了,帮助我理解比特币。 一个写着玩的 bitcoin 客户端,代码不复杂,轻松了解比特币。项目地址:https://github.com/jiangleo/b... 起因 看书确实是很好...
摘要:今天对象在学习时发现对象的方法并不能清理一级缓存同一下相同查询条件返回的结果还是旧值。测试代码如下上网搜索网上搜索找到了相同问题并没有人解答。例如查看官方文档实例有一个本地缓存在执行和时被清理。要明确地关闭它获取打算做更多的工作你可以调用。 今天对象在学习 Mybatis 时发现 org.apache.ibatis.session.SqlSession 对象的 clearCache()...
阅读 2669·2021-10-19 11:41
阅读 2494·2021-09-01 10:32
阅读 3439·2019-08-29 15:21
阅读 1890·2019-08-29 12:20
阅读 1225·2019-08-29 12:13
阅读 697·2019-08-26 12:24
阅读 2605·2019-08-26 10:26
阅读 916·2019-08-23 18:40