摘要:配置測試描述測試類技術部查詢表至此初步配置完成執行過程獲取解析成接收方法方法方法屬性定位方法數據綁定到具體方法提交傳輸獲取配置解析標簽對象獲取過程源碼使用
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
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| stopsession
獲取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 中 ,一個接口只能注冊一次
publicvoid 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, MapadditionalParameters) { 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
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/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()...
閱讀 2582·2021-10-19 11:41
閱讀 2420·2021-09-01 10:32
閱讀 3382·2019-08-29 15:21
閱讀 1760·2019-08-29 12:20
閱讀 1169·2019-08-29 12:13
閱讀 605·2019-08-26 12:24
閱讀 2524·2019-08-26 10:26
閱讀 836·2019-08-23 18:40