摘要:配置測(cè)試描述測(cè)試類技術(shù)部查詢表至此初步配置完成執(zhí)行過(guò)程獲取解析成接收方法方法方法屬性定位方法數(shù)據(jù)綁定到具體方法提交傳輸獲取配置解析標(biāo)簽對(duì)象獲取過(guò)程源碼使用
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
測(cè)試
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; }
測(cè)試類
public class Demo { public static void main(String[] args) throws Exception { Dept dept = new Dept(); dept.setDname("技術(shù)部"); 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(); } }
查詢表
至此初步配置完成
執(zhí)行過(guò)程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[數(shù)據(jù)綁定到具體sql] conditionF --> |org.apache.ibatis.executor.statement.PreparedStatementHandler update方法 提交| conditionG[傳輸sql] conditionG -->|commit| stopsession
獲取mybatils-config.xml 配置 解析xml標(biāo)簽
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 對(duì)象
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
獲取過(guò)程源碼
org.apache.ibatis.builder.xml.XMLConfigBuilder 使用parseConfiguration 方法將 mybatis-config.xml 中的mappers 標(biāo)簽內(nèi)容獲取到 mapperElement具體執(zhí)行獲取內(nèi)容 ,作用將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; } } }
當(dāng)前Configuration 下的mappedStatements 屬性
org.apache.ibatis.binding.MapperRegistry addMapper 方法,作用將解析到的接口對(duì)象放到configuration 中 ,一個(gè)接口只能注冊(cè)一次
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 來(lái)確認(rèn)加載具體的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(); } } }
根據(jù) loadXmlResource 中下面這行得知 , PojoMapper.xml 要和 PojoMapperInterface 放在一個(gè)路徑下
String xmlResource = this.type.getName().replace(".", "/") + ".xml";具體sql
org.apache.ibatis.builder.xml.XMLStatementBuilder parseStatementNode 方法解析sql語(yǔ)句
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語(yǔ)句
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
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/73404.html
摘要:源碼倉(cāng)庫(kù)本文倉(cāng)庫(kù)三層結(jié)構(gòu)表現(xiàn)層模型業(yè)務(wù)層持久層工作流程用戶前端控制器用戶發(fā)送請(qǐng)求前端控制器后端控制器根據(jù)用戶請(qǐng)求查詢具體控制器后端控制器前端控制器處理后結(jié)果前端控制器視圖視圖渲染視圖前端控制器返回視圖前端控制器用戶響應(yīng)結(jié) SpringMvc 【源碼倉(cāng)庫(kù)】【本文倉(cāng)庫(kù)】 三層結(jié)構(gòu) 表現(xiàn)層 MVC模型 業(yè)務(wù)層 service 持久層 dao 工作流程 用戶->前端控制器:用戶...
摘要:一個(gè)寫(xiě)著玩的客戶端,代碼不復(fù)雜,輕松了解比特幣。項(xiàng)目地址起因看書(shū)確實(shí)是很好的學(xué)習(xí)比特幣的方法,但是沒(méi)有代碼的幫助,理解比特幣如何實(shí)現(xiàn)時(shí),很是困難。后來(lái)發(fā)現(xiàn)一個(gè)用寫(xiě)的完整客戶端,就決定用它來(lái)研究比特幣源碼了,幫助我理解比特幣。 一個(gè)寫(xiě)著玩的 bitcoin 客戶端,代碼不復(fù)雜,輕松了解比特幣。項(xiàng)目地址:https://github.com/jiangleo/b... 起因 看書(shū)確實(shí)是很好...
摘要:一個(gè)寫(xiě)著玩的客戶端,代碼不復(fù)雜,輕松了解比特幣。項(xiàng)目地址起因看書(shū)確實(shí)是很好的學(xué)習(xí)比特幣的方法,但是沒(méi)有代碼的幫助,理解比特幣如何實(shí)現(xiàn)時(shí),很是困難。后來(lái)發(fā)現(xiàn)一個(gè)用寫(xiě)的完整客戶端,就決定用它來(lái)研究比特幣源碼了,幫助我理解比特幣。 一個(gè)寫(xiě)著玩的 bitcoin 客戶端,代碼不復(fù)雜,輕松了解比特幣。項(xiàng)目地址:https://github.com/jiangleo/b... 起因 看書(shū)確實(shí)是很好...
摘要:今天對(duì)象在學(xué)習(xí)時(shí)發(fā)現(xiàn)對(duì)象的方法并不能清理一級(jí)緩存同一下相同查詢條件返回的結(jié)果還是舊值。測(cè)試代碼如下上網(wǎng)搜索網(wǎng)上搜索找到了相同問(wèn)題并沒(méi)有人解答。例如查看官方文檔實(shí)例有一個(gè)本地緩存在執(zhí)行和時(shí)被清理。要明確地關(guān)閉它獲取打算做更多的工作你可以調(diào)用。 今天對(duì)象在學(xué)習(xí) Mybatis 時(shí)發(fā)現(xiàn) org.apache.ibatis.session.SqlSession 對(duì)象的 clearCache()...
閱讀 2594·2021-10-19 11:41
閱讀 2428·2021-09-01 10:32
閱讀 3386·2019-08-29 15:21
閱讀 1769·2019-08-29 12:20
閱讀 1173·2019-08-29 12:13
閱讀 611·2019-08-26 12:24
閱讀 2528·2019-08-26 10:26
閱讀 844·2019-08-23 18:40