本文共 8915 字,大约阅读时间需要 29 分钟。
就是把1条<select></select> 或 <insert/> 等变成1个MappedStatement
解析mybatis-config.xml
解析具体的mapper.xml,比如AccountMapper.xml
解析xml文件中各个节点,比如<select/>、<insert/>、<update/>、<delete/>节点
注解处理(Select、Insert、Update、Delete等)
protected SqlSessionFactory buildSqlSessionFactory() throws Exception {......................// 如果配置了mybatis.mapper-locationsif (this.mapperLocations != null) { if (this.mapperLocations.length == 0) { LOGGER.warn(() -> "Property 'mapperLocations' was specified but matching resources are not found."); } else { for (Resource mapperLocation : this.mapperLocations) { if (mapperLocation == null) { continue; } try { XMLMapperBuilder xmlMapperBuilder = new XMLMapperBuilder(mapperLocation.getInputStream(), targetConfiguration, mapperLocation.toString(), targetConfiguration.getSqlFragments()); xmlMapperBuilder.parse(); } catch (Exception e) { throw new NestedIOException("Failed to parse mapping resource: '" + mapperLocation + "'", e); } finally { ErrorContext.instance().reset(); } LOGGER.debug(() -> "Parsed mapper file: '" + mapperLocation + "'"); } } }......................}
解析xml文件中各个节点,比如<select/>、<insert/>、<update/>、<delete/>节点,内部会使用XMLScriptBuilder处理节点的sql部分,
每个节点(<select/>、<insert/>、<update/>、<delete/>)会生成1个MappedStatement,然后会放到Configuration的mappedStatements中
private void bindMapperForNamespace() { String namespace = builderAssistant.getCurrentNamespace(); if (namespace != null) { Class boundType = null; try { boundType = Resources.classForName(namespace); } catch (ClassNotFoundException e) { //ignore, bound type is not required } if (boundType != null) { if (!configuration.hasMapper(boundType)) { // Spring may not know the real resource name so we set a flag // to prevent loading again this resource from the mapper interface // look at MapperAnnotationBuilder#loadXmlResource configuration.addLoadedResource("namespace:" + namespace); configuration.addMapper(boundType); //添加Mapper } } } }
publicvoid addMapper(Class type) { if (type.isInterface()) { if (hasMapper(type)) { throw new BindingException("Type " + type + " is already known to the MapperRegistry."); } boolean loadCompleted = false; try { knownMappers.put(type, new MapperProxyFactory<>(type)); // It's important that the type is added before the parser is run // otherwise the binding may automatically be attempted by the // mapper parser. If the type is already known, it won't try. MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type); parser.parse(); loadCompleted = true; } finally { if (!loadCompleted) { knownMappers.remove(type); } } } }
public final class MappedStatement { private String resource; // file [E:\zyzhworkspace\springboot2\database\mybatis\mybatis-mapper\target\classes\com\kq\mybatis\mapper\AccountXmlMapper.xml] private Configuration configuration; private String id; private Integer fetchSize; private Integer timeout; private StatementType statementType; //STATEMENT, PREPARED, CALLABLE private ResultSetType resultSetType; private SqlSource sqlSource; private Cache cache; private ParameterMap parameterMap; private ListresultMaps; private boolean flushCacheRequired; private boolean useCache; private boolean resultOrdered; private SqlCommandType sqlCommandType; // UNKNOWN, INSERT, UPDATE, DELETE, SELECT, FLUSH; private KeyGenerator keyGenerator; private String[] keyProperties; private String[] keyColumns; private boolean hasNestedResultMaps; private String databaseId; private Log statementLog; private LanguageDriver lang; private String[] resultSets;}
public MappedStatement addMappedStatement(..........................MappedStatement statement = statementBuilder.build(); configuration.addMappedStatement(statement); // 放到configuration mappedStatements.put(ms.getId(), ms);// id比如: com.kq.mybatis.mapper.AccountXmlMapper.getAccountList return statement;}
解析注解(Select、Insert、Update、Delete)生成1个MappedStatement,然后会放到Configuration的mappedStatements中
public void parse() { String resource = type.toString(); if (!configuration.isResourceLoaded(resource)) { loadXmlResource(); // 从xml加载,有可能没有xml的mapper文件的 configuration.addLoadedResource(resource); // hashset 不会重复添加 assistant.setCurrentNamespace(type.getName()); // 设置namespace parseCache(); parseCacheRef(); Method[] methods = type.getMethods(); // 获得方法 for (Method method : methods) { try { // issue #237 if (!method.isBridge()) { parseStatement(method); } } catch (IncompleteElementException e) { configuration.addIncompleteMethod(new MethodResolver(this, method)); } } } parsePendingMethods(); }
void parseStatement(Method method) { Class parameterTypeClass = getParameterType(method); LanguageDriver languageDriver = getLanguageDriver(method); SqlSource sqlSource = getSqlSourceFromAnnotations(method, parameterTypeClass, languageDriver); if (sqlSource != null) { Options options = method.getAnnotation(Options.class); final String mappedStatementId = type.getName() + "." + method.getName(); // 比如: com.kq.mybatis.mapper.AccountMapper.getAccountList Integer fetchSize = null; Integer timeout = null; StatementType statementType = StatementType.PREPARED; ResultSetType resultSetType = configuration.getDefaultResultSetType(); SqlCommandType sqlCommandType = getSqlCommandType(method); boolean isSelect = sqlCommandType == SqlCommandType.SELECT; boolean flushCache = !isSelect; boolean useCache = isSelect; KeyGenerator keyGenerator; String keyProperty = null; String keyColumn = null; if (SqlCommandType.INSERT.equals(sqlCommandType) || SqlCommandType.UPDATE.equals(sqlCommandType)) { // first check for SelectKey annotation - that overrides everything else SelectKey selectKey = method.getAnnotation(SelectKey.class); if (selectKey != null) { keyGenerator = handleSelectKeyAnnotation(selectKey, mappedStatementId, getParameterType(method), languageDriver); keyProperty = selectKey.keyProperty(); } else if (options == null) { keyGenerator = configuration.isUseGeneratedKeys() ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE; } else { keyGenerator = options.useGeneratedKeys() ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE; keyProperty = options.keyProperty(); keyColumn = options.keyColumn(); } } else { keyGenerator = NoKeyGenerator.INSTANCE; // 没有KeyGenerator 排除Insert和Update } if (options != null) { if (FlushCachePolicy.TRUE.equals(options.flushCache())) { flushCache = true; } else if (FlushCachePolicy.FALSE.equals(options.flushCache())) { flushCache = false; } useCache = options.useCache(); fetchSize = options.fetchSize() > -1 || options.fetchSize() == Integer.MIN_VALUE ? options.fetchSize() : null; //issue #348 timeout = options.timeout() > -1 ? options.timeout() : null; statementType = options.statementType(); if (options.resultSetType() != ResultSetType.DEFAULT) { resultSetType = options.resultSetType(); } } String resultMapId = null; // 比如: com.kq.mybatis.mapper.AccountMapper.getAccountList-void ResultMap resultMapAnnotation = method.getAnnotation(ResultMap.class); if (resultMapAnnotation != null) { resultMapId = String.join(",", resultMapAnnotation.value()); } else if (isSelect) { resultMapId = parseResultMap(method); } assistant.addMappedStatement( mappedStatementId, sqlSource, statementType, sqlCommandType, fetchSize, timeout, // ParameterMapID null, parameterTypeClass, resultMapId, getReturnType(method), resultSetType, flushCache, useCache, // TODO gcode issue #577 false, keyGenerator, keyProperty, keyColumn, // DatabaseID null, languageDriver, // ResultSets options != null ? nullOrEmpty(options.resultSets()) : null); } }
转载地址:http://bexwb.baihongyu.com/