public static void main(String[] args) throws Exception {
Reader reader = Resources.getResourceAsReader("mybatis/SqlMapconfig.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader);
SqlSession sqlSession = sqlSessionFactory.openSession();
try {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
/* User user = new User(1L, "哈哈", "哈哈");
mapper.insertUser(user);
sqlSession.commit();*/
User user1 = mapper.getUser(24);
System.out.println(user1);
} finally {
sqlSession.close();
}
}
public static Reader getResourceAsReader(String resource) throws IOException {
Reader reader;
if (charset == null) {
reader = new InputStreamReader(getResourceAsStream(resource));
} else {
reader = new InputStreamReader(getResourceAsStream(resource), charset);
}
return reader;
}
public static InputStream getResourceAsStream(String resource) throws IOException {
return getResourceAsStream(null, resource);
}
public static InputStream getResourceAsStream(ClassLoader loader, String resource) throws IOException {
InputStream in = classLoaderWrapper.getResourceAsStream(resource, loader);
if (in == null) {
throw new IOException("Could not find resource " + resource);
}
return in;
}
public InputStream getResourceAsStream(String resource, ClassLoader classLoader) {
return getResourceAsStream(resource, getClassLoaders(classLoader));
}
/**
* 返回Class Loader[]数组,该数组指明了类加载器的使用顺序
* @param classLoader
* @return
*/
ClassLoader[] getClassLoaders(ClassLoader classLoader) {
return new ClassLoader[]{
//参数指定的类加载器
classLoader,
//系统指定的默认类加载器
defaultClassLoader,
// 当前线程绑定的类加载器
Thread.currentThread().getContextClassLoader(),
// 加载当前类所使用的类加载器
getClass().getClassLoader(),
//System Cl assLoader
systemClassLoader};
}
public SqlSessionFactory build(Reader reader) {
return build(reader, null, null);
}
public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
reader.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
public XMLConfigBuilder(Reader reader, String environment, Properties props) {
this(new XPathParser(reader, true, props, new XMLMapperEntityResolver()), environment, props);
}
public XPathParser(Reader reader, boolean validation, Properties variables, EntityResolver entityResolver) {
commonConstructor(validation, variables, entityResolver);
this.document = createDocument(new InputSource(reader));
}
private void commonConstructor(boolean validation, Properties variables, EntityResolver entityResolver) {
this.validation = validation;
this.entityResolver = entityResolver;
this.variables = variables;
XPathFactory factory = XPathFactory.newInstance();
this.xpath = factory.newXPath();
}
private Document createDocument(InputSource inputSource) {
// important: this must only be called AFTER common constructor
try {
// 创建工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
factory.setValidating(validation);
factory.setNamespaceAware(false);
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(false);
factory.setCoalescing(false);
factory.setExpandEntityReferences(true);
// 得到dom解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//设置DTD解析器
builder.setEntityResolver(entityResolver);
builder.setErrorHandler(new ErrorHandler() {
@Override
public void error(SAXParseException exception) throws SAXException {
throw exception;
}
@Override
public void fatalError(SAXParseException exception) throws SAXException {
throw exception;
}
@Override
public void warning(SAXParseException exception) throws SAXException {
// NOP
}
});
//加载XML
return builder.parse(inputSource);
} catch (Exception e) {
throw new BuilderException("Error creating document instance. Cause: " + e, e);
}
}
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
try {
if (systemId != null) {
String lowerCaseSystemId = systemId.toLowerCase(Locale.ENGLISH);
//查找sysId指定的DTD文档,并读取
if (lowerCaseSystemId.contains(MYBATIS_CONFIG_SYSTEM) || lowerCaseSystemId.contains(IBATIS_CONFIG_SYSTEM)) {
return getInputSource(MYBATIS_CONFIG_DTD, publicId, systemId);
} else if (lowerCaseSystemId.contains(MYBATIS_MAPPER_SYSTEM) || lowerCaseSystemId.contains(IBATIS_MAPPER_SYSTEM)) {
return getInputSource(MYBATIS_MAPPER_DTD, publicId, systemId);
}
}
return null;
} catch (Exception e) {
throw new SAXException(e.toString());
}
}
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration());
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
//标记没有解析过mybatis-config.xml 配置文件
this.parsed = false;
this.environment = environment;
//设置Xpath
this.parser = parser;
}
public Configuration() {
//注册别名
typeAliasRegistry.registerAlias("JDBC", JdbcTransactionFactory.class);
typeAliasRegistry.registerAlias("MANAGED", ManagedTransactionFactory.class);
typeAliasRegistry.registerAlias("JNDI", JndiDataSourceFactory.class);
typeAliasRegistry.registerAlias("POOLED", PooledDataSourceFactory.class);
typeAliasRegistry.registerAlias("UNPOOLED", UnpooledDataSourceFactory.class);
typeAliasRegistry.registerAlias("PERPETUAL", PerpetualCache.class);
typeAliasRegistry.registerAlias("FIFO", FifoCache.class);
typeAliasRegistry.registerAlias("LRU", LruCache.class);
typeAliasRegistry.registerAlias("SOFT", SoftCache.class);
typeAliasRegistry.registerAlias("WEAK", WeakCache.class);
typeAliasRegistry.registerAlias("DB_VENDOR", VendorDatabaseIdProvider.class);
typeAliasRegistry.registerAlias("XML", XMLLanguageDriver.class);
typeAliasRegistry.registerAlias("RAW", RawLanguageDriver.class);
typeAliasRegistry.registerAlias("SLF4J", Slf4jImpl.class);
typeAliasRegistry.registerAlias("COMMONS_LOGGING", JakartaCommonsLoggingImpl.class);
typeAliasRegistry.registerAlias("LOG4J", Log4jImpl.class);
typeAliasRegistry.registerAlias("LOG4J2", Log4j2Impl.class);
typeAliasRegistry.registerAlias("JDK_LOGGING", Jdk14LoggingImpl.class);
typeAliasRegistry.registerAlias("STDOUT_LOGGING", StdOutImpl.class);
typeAliasRegistry.registerAlias("NO_LOGGING", NoLoggingImpl.class);
typeAliasRegistry.registerAlias("CGLIB", CglibProxyFactory.class);
typeAliasRegistry.registerAlias("JAVASSIST", JavassistProxyFactory.class);
//将XmlLanguageDriver 设置为默认的动态SQL 语言驱动器
languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
languageRegistry.register(RawLanguageDriver.class);
}
public Configuration parse() {
if (parsed) {
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;//标记已经解析xml配置文件configuration标签
//在mybatis-config.xml 配置文件中查找< configuration >节点,并开始解析
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
public XNode evalNode(String expression) {
return evalNode(document, expression);
}
public XNode evalNode(Object root, String expression) {
Node node = (Node) evaluate(expression, root, XPathConstants.NODE);//xpath解析
if (node == null) {
return null;
}
return new XNode(this, node, variables);
}
public XNode(XPathParser xpathParser, Node node, Properties variables) {
this.xpathParser = xpathParser;
this.node = node;
this.name = node.getNodeName();//设置节点名
this.variables = variables;
this.attributes = parseAttributes(node);//获取标签里面设置的属性
this.body = parseBody(node);//解析标签里面的内容
}
private Properties parseAttributes(Node n) {
Properties attributes = new Properties();
//获取节点的属性集合
NamedNodeMap attributeNodes = n.getAttributes();
if (attributeNodes != null) {
for (int i = 0; i < attributeNodes.getLength(); i++) {
Node attribute = attributeNodes.item(i);
//使用PropertyParser 处理每个属性中的占位符
String value = PropertyParser.parse(attribute.getNodeValue(), variables);
attributes.put(attribute.getNodeName(), value);
}
}
return attributes;
}
public static String parse(String string, Properties variables) {
VariableTokenHandler handler = new VariableTokenHandler(variables);
//指定处理的占位符格式为${}
GenericTokenParser parser = new GenericTokenParser("${", "}", handler);
return parser.parse(string);
}
/**
* 将text根据前后占位符解析
* @param text
* @return
*/
public String parse(String text) {
if (text == null || text.isEmpty()) {
return "";
}
// search open token
//查找第一个开启占位符位置
int start = text.indexOf(openToken);
if (start == -1) {
return text;
}
char[] src = text.toCharArray();
int offset = 0;
//线程安全,记录占位符的值
final StringBuilder builder = new StringBuilder();
StringBuilder expression = null;
while (start > -1) {
if (start > 0 && src[start - 1] == '\\') {
// this open token is escaped. remove the backslash and continue.
//遇到转义的开始标记,直接将前面的字符串以及开始标记追加
builder.append(src, offset, start - offset - 1).append(openToken);
offset = start + openToken.length();
} else {
// found open token. let's search close token.
//查找到开始标记,且未转义
if (expression == null) {
expression = new StringBuilder();
} else {
expression.setLength(0);
}
//前面字符追加
builder.append(src, offset, start - offset);
offset = start + openToken.length();
//从offset后继续查找结束标记
int end = text.indexOf(closeToken, offset);
while (end > -1) {
if (end > offset && src[end - 1] == '\\') {
// this close token is escaped. remove the backslash and continue.
//处理转义的结束标记
expression.append(src, offset, end - offset - 1).append(closeToken);
offset = end + closeToken.length();
end = text.indexOf(closeToken, offset);
} else {
//将开始标记和结束标记之间字符添加
expression.append(src, offset, end - offset);
break;
}
}
if (end == -1) {
//未找到结束标记
// close token was not found.
builder.append(src, start, src.length - start);
offset = src.length;
} else {
//将占位符的值交给handler处理,并保存builder
builder.append(handler.handleToken(expression.toString()));
offset = end + closeToken.length();
}
}
//移动start
start = text.indexOf(openToken, offset);
}
if (offset < src.length) {
builder.append(src, offset, src.length - offset);
}
return builder.toString();
}
@Override
public String handleToken(String content) {
//variables非空
if (variables != null) {
String key = content;
//是否支持占位符中使用默认值功能
if (enableDefaultValue) {
//查找分割符
final int separatorIndex = content.indexOf(defaultValueSeparator);
String defaultValue = null;
if (separatorIndex >= 0) {
//获取占位符名称
key = content.substring(0, separatorIndex);
//获取默认值
defaultValue = content.substring(separatorIndex + defaultValueSeparator.length());
}
if (defaultValue != null) {
//查找指定占位符
return variables.getProperty(key, defaultValue);
}
}
//不支持默认值,则直接找
if (variables.containsKey(key)) {
return variables.getProperty(key);
}
}
//variables空
return "${" + content + "}";
}
}
private String parseBody(Node node) {
//获取标签内容,且解析${}占位符里面的值
String data = getBodyData(node);
//当前节点不是文本节点
if (data == null) {
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node child = children.item(i);
data = getBodyData(child);
if (data != null) {
break;
}
}
}
return data;
}
private String getBodyData(Node child) {
//只处理文本内容
if (child.getNodeType() == Node.CDATA_SECTION_NODE
|| child.getNodeType() == Node.TEXT_NODE) {
String data = ((CharacterData) child).getData();
//使用PropertyParser 处理文本节点中的占位符
data = PropertyParser.parse(data, variables);
return data;
}
return null;
}
private void parseConfiguration(XNode root) {
try {
// issue #117 read properties first
//解析<properties>节点
propertiesElement(root.evalNode("properties"));
//解析<settings>节点
Properties settings = settingsAsProperties(root.evalNode("settings"));
//设置vfsimpl 字段
loadCustomVfs(settings);
loadCustomLogImpl(settings);
typeAliasesElement(root.evalNode("typeAliases"));
pluginElement(root.evalNode("plugins"));
objectFactoryElement(root.evalNode("objectFactory"));
objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
reflectorFactoryElement(root.evalNode("reflectorFactory"));
settingsElement(settings);
// read it after objectFactory and objectWrapperFactory issue #631
//每个<environment> 节点对应一种环境的配置。
environmentsElement(root.evalNode("environments"));
databaseIdProviderElement(root.evalNode("databaseIdProvider"));
typeHandlerElement(root.evalNode("typeHandlers"));
mapperElement(root.evalNode("mappers"));
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);
}
}
private void propertiesElement(XNode context) throws Exception {
if (context != null) {
//解析<properties >的子节点(<property>标签)的name 和value 属性,并记录到Properties 中
Properties defaults = context.getChildrenAsProperties();
//解析< properties >的resource 和url ,这两个属性用于确定properties 配置文件的位置
String resource = context.getStringAttribute("resource");
String url = context.getStringAttribute("url");
//resource 属性和url 属性不能同时存在,否则会抛出异常
if (resource != null && url != null) {
throw new BuilderException("The properties element cannot specify both a URL and a resource based property file reference. Please specify one or the other.");
}
//加载resource或url
if (resource != null) {
defaults.putAll(Resources.getResourceAsProperties(resource));
} else if (url != null) {
defaults.putAll(Resources.getUrlAsProperties(url));
}
//与configuration对象中的variables集合合并
Properties vars = configuration.getVariables();
if (vars != null) {
defaults.putAll(vars);
}
//更新XPathParser和Configuration的variables字段
parser.setVariables(defaults);
configuration.setVariables(defaults);
}
}
private Properties settingsAsProperties(XNode context) {
if (context == null) {
return new Properties();
}
//解析< settings >的子节点(< setting >标签)的name 和value 属性,并返回Properties 对象
Properties props = context.getChildrenAsProperties();
// Check that all settings are known to the configuration class
//创建Configurat对应的MetaClass 对象
MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory);
//检测Configuration 中是否定义了key 指定属性相应的setter 方法
for (Object key : props.keySet()) {
if (!metaConfig.hasSetter(String.valueOf(key))) {
throw new BuilderException("The setting " + key + " is not known. Make sure you spelled it correctly (case sensitive).");
}
}
return props;
}
private void settingsElement(Properties props) {
configuration.setAutoMappingBehavior(AutoMappingBehavior.valueOf(props.getProperty("autoMappingBehavior", "PARTIAL")));
configuration.setAutoMappingUnknownColumnBehavior(AutoMappingUnknownColumnBehavior.valueOf(props.getProperty("autoMappingUnknownColumnBehavior", "NONE")));
configuration.setCacheEnabled(booleanValueOf(props.getProperty("cacheEnabled"), true));
configuration.setProxyFactory((ProxyFactory) createInstance(props.getProperty("proxyFactory")));
configuration.setLazyLoadingEnabled(booleanValueOf(props.getProperty("lazyLoadingEnabled"), false));
configuration.setAggressiveLazyLoading(booleanValueOf(props.getProperty("aggressiveLazyLoading"), false));
configuration.setMultipleResultSetsEnabled(booleanValueOf(props.getProperty("multipleResultSetsEnabled"), true));
configuration.setUseColumnLabel(booleanValueOf(props.getProperty("useColumnLabel"), true));
configuration.setUseGeneratedKeys(booleanValueOf(props.getProperty("useGeneratedKeys"), false));
configuration.setDefaultExecutorType(ExecutorType.valueOf(props.getProperty("defaultExecutorType", "SIMPLE")));
configuration.setDefaultStatementTimeout(integerValueOf(props.getProperty("defaultStatementTimeout"), null));
configuration.setDefaultFetchSize(integerValueOf(props.getProperty("defaultFetchSize"), null));
configuration.setDefaultResultSetType(resolveResultSetType(props.getProperty("defaultResultSetType")));
configuration.setMapUnderscoreToCamelCase(booleanValueOf(props.getProperty("mapUnderscoreToCamelCase"), false));
configuration.setSafeRowBoundsEnabled(booleanValueOf(props.getProperty("safeRowBoundsEnabled"), false));
configuration.setLocalCacheScope(LocalCacheScope.valueOf(props.getProperty("localCacheScope", "SESSION")));
configuration.setJdbcTypeForNull(JdbcType.valueOf(props.getProperty("jdbcTypeForNull", "OTHER")));
configuration.setLazyLoadTriggerMethods(stringSetValueOf(props.getProperty("lazyLoadTriggerMethods"), "equals,clone,hashCode,toString"));
configuration.setSafeResultHandlerEnabled(booleanValueOf(props.getProperty("safeResultHandlerEnabled"), true));
configuration.setDefaultScriptingLanguage(resolveClass(props.getProperty("defaultScriptingLanguage")));
configuration.setDefaultEnumTypeHandler(resolveClass(props.getProperty("defaultEnumTypeHandler")));
configuration.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
configuration.setUseActualParamName(booleanValueOf(props.getProperty("useActualParamName"), true));
configuration.setReturnInstanceForEmptyRow(booleanValueOf(props.getProperty("returnInstanceForEmptyRow"), false));
configuration.setLogPrefix(props.getProperty("logPrefix"));
configuration.setConfigurationFactory(resolveClass(props.getProperty("configurationFactory")));
}
private void typeAliasesElement(XNode parent) {
if (parent != null) {
//处理全部子节点
for (XNode child : parent.getChildren()) {
//处理< package >节点
if ("package".equals(child.getName())) {
// 获取指定的包名
String typeAliasPackage = child.getStringAttribute("name");
//通过TypeAliasRegistry 扫描指定包中所有的类,并解析@ Alias注解,完成别名注册
configuration.getTypeAliasRegistry().registerAliases(typeAliasPackage);
} else {
//处理< typeAlias >节点
String alias = child.getStringAttribute("alias");
String type = child.getStringAttribute("type");
try {
Class<?> clazz = Resources.classForName(type);
if (alias == null) {
// 扫描@Alias注解,完成注册
typeAliasRegistry.registerAlias(clazz);
} else {
// 注册别名
typeAliasRegistry.registerAlias(alias, clazz);
}
} catch (ClassNotFoundException e) {
throw new BuilderException("Error registering typeAlias for '" + alias + "'. Cause: " + e, e);
}
}
}
}
}
private void pluginElement(XNode parent) throws Exception {
if (parent != null) {
//追历全部子节点(即< plugin>节点)
for (XNode child : parent.getChildren()) {
//获取<plugin>节点的interceptor 属性的值
String interceptor = child.getStringAttribute("interceptor");
//获取<plugin>节点下<properties>配置的信息,并形成Properties 对象
Properties properties = child.getChildrenAsProperties();
//通过前面介绍的TypeAliasRegistry 解析别名之后,实例化Interceptor 对象
Interceptor interceptorInstance = (Interceptor) resolveClass(interceptor).getDeclaredConstructor().newInstance();
// 设置Interceptor 的属性
interceptorInstance.setProperties(properties);
// 记录Interceptor 对象
configuration.addInterceptor(interceptorInstance);
}
}
}
protected <T> Class<? extends T> resolveClass(String alias) {
if (alias == null) {
return null;
}
try {
return resolveAlias(alias);
} catch (Exception e) {
throw new BuilderException("Error resolving class. Cause: " + e, e);
}
}
protected <T> Class<? extends T> resolveAlias(String alias) {
return typeAliasRegistry.resolveAlias(alias);
}
public <T> Class<T> resolveAlias(String string) {
try {
if (string == null) {
return null;
}
// issue #748
String key = string.toLowerCase(Locale.ENGLISH);
Class<T> value;
if (typeAliases.containsKey(key)) {
value = (Class<T>) typeAliases.get(key);
} else {
value = (Class<T>) Resources.classForName(string);
}
return value;
} catch (ClassNotFoundException e) {
throw new TypeException("Could not resolve type alias '" + string + "'. Cause: " + e, e);
}
}
public void addInterceptor(Interceptor interceptor) {
interceptorChain.addInterceptor(interceptor);
}
public void addInterceptor(Interceptor interceptor) {
interceptors.add(interceptor);
}
private void objectFactoryElement(XNode context) throws Exception {
if (context != null) {
//获取<objectFactory> 节点的type 属性
String type = context.getStringAttribute("type");
//获取<objectFactory>节点下配置的信息,并形成Properties对象
Properties properties = context.getChildrenAsProperties();
//进行别名解析后,实例化自定义ObjectFactory实现
ObjectFactory factory = (ObjectFactory) resolveClass(type).getDeclaredConstructor().newInstance();
//设置自定义ObjectFactory 的属性,完成初始化的相关操作
factory.setProperties(properties);
//将自定义ObjectFactory 对象记录到configuration对象的objectFactory 字段中,待后续使用
configuration.setObjectFactory(factory);
}
}
private void environmentsElement(XNode context) throws Exception {
if (context != null) {
//未指定XMLConfigBuilder.environment 字段,则使用default属性指定的< environment>
if (environment == null) {
environment = context.getStringAttribute("default");
}
//遍历子节点(即< environment > 节点)
for (XNode child : context.getChildren()) {
String id = child.getStringAttribute("id");
//与XMLConfigBuilder.environment匹配
if (isSpecifiedEnvironment(id)) {
//创建TransactionFactory ,具体实现是先通过TypeAliasRegistry 解析别名之后,实例化
TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
//创建DataSourceFactory 和DataSource
DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
DataSource dataSource = dsFactory.getDataSource();
//创建Environment, Environment 中封装了上面创建的TransactionFactory 对象 以及DataSource 对象。这里应用了建造者模式
Environment.Builder environmentBuilder = new Environment.Builder(id)
.transactionFactory(txFactory)
.dataSource(dataSource);
//将Environment 对象记录到Configuration.environment 字段中
configuration.setEnvironment(environmentBuilder.build());
}
}
}
}
其他过程非常简单就不贴出来了
private void databaseIdProviderElement(XNode context) throws Exception {
DatabaseIdProvider databaseIdProvider = null;
if (context != null) {
String type = context.getStringAttribute("type");
// awful patch to keep backward compatibility
//为了保证兼容性,修改type 取值
if ("VENDOR".equals(type)) {
type = "DB_VENDOR";
}
Properties properties = context.getChildrenAsProperties();
//创建DatabaseidProvider 对象
databaseIdProvider = (DatabaseIdProvider) resolveClass(type).getDeclaredConstructor().newInstance();
//配置DatabaseidProvider ,完成初始化
databaseIdProvider.setProperties(properties);
}
Environment environment = configuration.getEnvironment();
if (environment != null && databaseIdProvider != null) {
//通过前面确定的DataSource 获取database Id , 并记录到configuration.databaseid 字段中
String databaseId = databaseIdProvider.getDatabaseId(environment.getDataSource());
configuration.setDatabaseId(databaseId);
}
}
private void typeHandlerElement(XNode parent) {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String typeHandlerPackage = child.getStringAttribute("name");
typeHandlerRegistry.register(typeHandlerPackage);
} else {
String javaTypeName = child.getStringAttribute("javaType");
String jdbcTypeName = child.getStringAttribute("jdbcType");
String handlerTypeName = child.getStringAttribute("handler");
Class<?> javaTypeClass = resolveClass(javaTypeName);
JdbcType jdbcType = resolveJdbcType(jdbcTypeName);
Class<?> typeHandlerClass = resolveClass(handlerTypeName);
if (javaTypeClass != null) {
if (jdbcType == null) {
typeHandlerRegistry.register(javaTypeClass, typeHandlerClass);
} else {
typeHandlerRegistry.register(javaTypeClass, jdbcType, typeHandlerClass);
}
} else {
typeHandlerRegistry.register(typeHandlerClass);
}
}
}
}
}
private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
//处理< mappers >的子节点
for (XNode child : parent.getChildren()) {
//
if ("package".equals(child.getName())) {
String mapperPackage = child.getStringAttribute("name");
//扫描指定的包,并向MapperRegistry 注册Mapper 接口
configuration.addMappers(mapperPackage);
} else {
//获取<mapper >节点的resource 、url 、class 属性,这三个属性互斥
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
//如果<mapper >节点指定了resource 或是url 属性,则创建XMLMapperBuilder 对象,并通过该对象解析resource 或是url 属性指定的Mapper 配置文件
if (resource != null && url == null && mapperClass == null) {
ErrorContext.instance().resource(resource);
InputStream inputStream = Resources.getResourceAsStream(resource);
//创建XMLMapperBu 工lder 对象,解析映射配置文件
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url != null && mapperClass == null) {
ErrorContext.instance().resource(url);
InputStream inputStream = Resources.getUrlAsStream(url);
//创建XMLMapperBuilder 对象, 解析映射配置文件
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
mapperParser.parse();
} else if (resource == null && url == null && mapperClass != null) {
//如果<mapper >节点指定了class属性,则向MapperRegistry 注册该Mapper 接口
Class<?> mapperInterface = Resources.classForName(mapperClass);
configuration.addMapper(mapperInterface);
} else {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");
}
}
}
}
}
public void parse() {
//判断是否已经加载过该映射文件
if (!configuration.isResourceLoaded(resource)) {
configurationElement(parser.evalNode("/mapper"));
configuration.addLoadedResource(resource);
//注册Mapper 接口
bindMapperForNamespace();
}
//处理configurationElement ()方法中解析失败的< resultMap > 节点
parsePendingResultMaps();
//处理configurationElement ()方法中解析失败的< cache-ref >节点
parsePendingCacheRefs();
//处理configurationElement ()方法中解析失败的SQL 语句节点
parsePendingStatements();
}
private void configurationElement(XNode context) {
try {
//获取<mapper > 节点的namespace 属性
String namespace = context.getStringAttribute("namespace");
if (namespace == null || namespace.isEmpty()) {
throw new BuilderException("Mapper's namespace cannot be empty");
}
//设置MapperBuilderAssistant的currentNamespace 字段,记录当前命名空间
builderAssistant.setCurrentNamespace(namespace);
//解析< cache - ref > 节点
//多个namespace 共用同一个二级缓存,即同一个Cache 对象,
cacheRefElement(context.evalNode("cache-ref"));
//解析< cache >节点,开启二级缓存
cacheElement(context.evalNode("cache"));
//解析< parameterMap >节点(该节点已废弃,不再推荐使用)
parameterMapElement(context.evalNodes("/mapper/parameterMap"));
//解析< resultMap >节点
resultMapElements(context.evalNodes("/mapper/resultMap"));
//解析< sql >节点
sqlElement(context.evalNodes("/mapper/sql"));
//解析< select >、< insert >、< update >、< delete >SQL 节点
buildStatementFromContext(context.evalNodes("select|insert|update|delete"));
} catch (Exception e) {
throw new BuilderException("Error parsing Mapper XML. The XML location is '" + resource + "'. Cause: " + e, e);
}
}
针对cache和cache-ref详情请看缓存
crud请看下方crud
private ResultMap resultMapElement(XNode resultMapNode) {
return resultMapElement(resultMapNode, Collections.emptyList(), null);
}
private ResultMap resultMapElement(XNode resultMapNode, List<ResultMapping> additionalResultMappings, Class<?> enclosingType) {
ErrorContext.instance().activity("processing " + resultMapNode.getValueBasedIdentifier());
//获取< resultMap >节点的type 属性,表示结果集集将被映射成type 指定类型的对象,
String type = resultMapNode.getStringAttribute("type",
resultMapNode.getStringAttribute("ofType",
resultMapNode.getStringAttribute("resultType",
resultMapNode.getStringAttribute("javaType"))));
//解析type 类型
Class<?> typeClass = resolveClass(type);
if (typeClass == null) {
typeClass = inheritEnclosingType(resultMapNode, enclosingType);
}
Discriminator discriminator = null;
//该集合用于记录解析的结果
List<ResultMapping> resultMappings = new ArrayList<>(additionalResultMappings);
//处理< resultMap > 的子节点
List<XNode> resultChildren = resultMapNode.getChildren();
for (XNode resultChild : resultChildren) {
if ("constructor".equals(resultChild.getName())) {
//处理<constructor> 节点
processConstructorElement(resultChild, typeClass, resultMappings);
} else if ("discriminator".equals(resultChild.getName())) {
//处理<discriminator>节点
discriminator = processDiscriminatorElement(resultChild, typeClass, resultMappings);
} else {
// 处理< id>、<result>、<association>、<collection >等节点
List<ResultFlag> flags = new ArrayList<>();
if ("id".equals(resultChild.getName())) {
// 如果是< id>节点,则向flags 集合中添加ResultFlag.ID
flags.add(ResultFlag.ID);
}
// 创建ResultMapping 对象,并添加到resultMappings 集合中保存
resultMappings.add(buildResultMappingFromContext(resultChild, typeClass, flags));
}
}
//获取< resultMap >的id 属性,默认值会拼笨所有父节点的id 或value 或Property值
String id = resultMapNode.getStringAttribute("id",
resultMapNode.getValueBasedIdentifier());
//获取< resultMap >节点的extends 属性,该属性指定了该< resultMap>节点的继承关系
String extend = resultMapNode.getStringAttribute("extends");
//读取< resultMap >节点的autoMapping 属性, 将该属性设置为true ,则启动自动映射功能
//即自动查找与列名同名的属性名,并调用setter 方法。而设置为false 后, 9)1] 需
//要在< resultMap > 节点内明确注明映射关系才会调用对应的setter 方法。
Boolean autoMapping = resultMapNode.getBooleanAttribute("autoMapping");
ResultMapResolver resultMapResolver = new ResultMapResolver(builderAssistant, id, typeClass, extend, discriminator, resultMappings, autoMapping);
try {
//创建ResultMap 对象,并添加到Configuration.resultMaps 集合中,该集合是StrictMap 类型
return resultMapResolver.resolve();
} catch (IncompleteElementException e) {
configuration.addIncompleteResultMap(resultMapResolver);
throw e;
}
}
private void processConstructorElement(XNode resultChild, Class<?> resultType, List<ResultMapping> resultMappings) {
// 获取< constructor >节点的子节点
List<XNode> argChildren = resultChild.getChildren();
for (XNode argChild : argChildren) {
List<ResultFlag> flags = new ArrayList<>();
//添加CONSTRUCTOR 标志
flags.add(ResultFlag.CONSTRUCTOR);
if ("idArg".equals(argChild.getName())) {
//对于<idArg>节点,添加ID标志
flags.add(ResultFlag.ID);
}
//创建ResultMapping 对象,并添加到resultMappings 集合中
resultMappings.add(buildResultMappingFromContext(argChild, resultType, flags));
}
}
private Discriminator processDiscriminatorElement(XNode context, Class<?> resultType, List<ResultMapping> resultMappings) {
String column = context.getStringAttribute("column");
String javaType = context.getStringAttribute("javaType");
String jdbcType = context.getStringAttribute("jdbcType");
String typeHandler = context.getStringAttribute("typeHandler");
Class<?> javaTypeClass = resolveClass(javaType);
Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
//处理<discriminator >节点的子节点
Map<String, String> discriminatorMap = new HashMap<>();
for (XNode caseChild : context.getChildren()) {
String value = caseChild.getStringAttribute("value");
//调用processNestedResultMappings ( ) 方法创建嵌套的ResultMap 对象
String resultMap = caseChild.getStringAttribute("resultMap", processNestedResultMappings(caseChild, resultMappings, resultType));
//记录该列值与对应选择的ResultMap 的Id
discriminatorMap.put(value, resultMap);
}
//创建Discriminator 对象
return builderAssistant.buildDiscriminator(resultType, column, javaTypeClass, jdbcTypeEnum, typeHandlerClass, discriminatorMap);
}
private ResultMapping buildResultMappingFromContext(XNode context, Class<?> resultType, List<ResultFlag> flags) {
String property;
if (flags.contains(ResultFlag.CONSTRUCTOR)) {
property = context.getStringAttribute("name");
} else {
property = context.getStringAttribute("property");
}
String column = context.getStringAttribute("column");
String javaType = context.getStringAttribute("javaType");
String jdbcType = context.getStringAttribute("jdbcType");
String nestedSelect = context.getStringAttribute("select");
//如果未指定< association >节点的resultMap属性,则是匿名的嵌套映射,需要通过
//processNestedResultMappings()方法解析该匿名的嵌套映射
String nestedResultMap = context.getStringAttribute("resultMap", () ->
processNestedResultMappings(context, Collections.emptyList(), resultType));
String notNullColumn = context.getStringAttribute("notNullColumn");
String columnPrefix = context.getStringAttribute("columnPrefix");
String typeHandler = context.getStringAttribute("typeHandler");
String resultSet = context.getStringAttribute("resultSet");
String foreignColumn = context.getStringAttribute("foreignColumn");
boolean lazy = "lazy".equals(context.getStringAttribute("fetchType", configuration.isLazyLoadingEnabled() ? "lazy" : "eager"));
//解析javaType 、typeHandler 和jdbcType
Class<?> javaTypeClass = resolveClass(javaType);
Class<? extends TypeHandler<?>> typeHandlerClass = resolveClass(typeHandler);
JdbcType jdbcTypeEnum = resolveJdbcType(jdbcType);
//创建ResultMapping 对象
return builderAssistant.buildResultMapping(resultType, property, column, javaTypeClass, jdbcTypeEnum, nestedSelect, nestedResultMap, notNullColumn, columnPrefix, typeHandlerClass, flags, resultSet, foreignColumn, lazy);
}
public ResultMapping buildResultMapping(
Class<?> resultType,
String property,
String column,
Class<?> javaType,
JdbcType jdbcType,
String nestedSelect,
String nestedResultMap,
String notNullColumn,
String columnPrefix,
Class<? extends TypeHandler<?>> typeHandler,
List<ResultFlag> flags,
String resultSet,
String foreignColumn,
boolean lazy) {
//解析< resultType >节点指定的property 属性的类型
Class<?> javaTypeClass = resolveResultJavaType(resultType, property, javaType);
//获取typeHandler 指定的TypeHandler 对象,底层依赖于typeHandlerRegistry ,
TypeHandler<?> typeHandlerInstance = resolveTypeHandler(javaTypeClass, typeHandler);
//解析column 属性值,当column 是” { propl=coll , prop2=col2 }” 形式时, 会解析成ResultMapping 对象集合,
// column 的这种形式主要用于嵌套查询的参数传递,
List<ResultMapping> composites;
if ((nestedSelect == null || nestedSelect.isEmpty()) && (foreignColumn == null || foreignColumn.isEmpty())) {
composites = Collections.emptyList();
} else {
composites = parseCompositeColumnName(column);
}
return new ResultMapping.Builder(configuration, property, column, javaTypeClass)
.jdbcType(jdbcType)
.nestedQueryId(applyCurrentNamespace(nestedSelect, true))
.nestedResultMapId(applyCurrentNamespace(nestedResultMap, true))
.resultSet(resultSet)
.typeHandler(typeHandlerInstance)
.flags(flags == null ? new ArrayList<>() : flags)
.composites(composites)
.notNullColumns(parseMultipleColumnNames(notNullColumn))
.columnPrefix(columnPrefix)
.foreignColumn(foreignColumn)
.lazy(lazy)
.build();
}
private void sqlElement(List<XNode> list) {
if (configuration.getDatabaseId() != null) {
sqlElement(list, configuration.getDatabaseId());
}
sqlElement(list, null);
}
private void sqlElement(List<XNode> list, String requiredDatabaseId) {
//遥历< sql >节点
for (XNode context : list) {
//获取databaseid 属性
String databaseId = context.getStringAttribute("databaseId");
//获取id 属性
String id = context.getStringAttribute("id");
//为id 添加命名空间
id = builderAssistant.applyCurrentNamespace(id, false);
//检测< sql >的database Id 与当前Configuration 中记录的database Id 是否一致
if (databaseIdMatchesCurrent(id, databaseId, requiredDatabaseId)) {
//记录到XMLMapperBuilder.sqlFragments ( Map
// 在XMLMapperBuilder的构造函数中,可以看到该字段指向了Configuration.sqlFragments 集合
sqlFragments.put(id, context);
}
}
}
/**
* 映射配置文件与对应Mapper 接口的绑定
*/
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
}
// 是否已经加载了boundType 接口
if (boundType != null && !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
// 追加namespace前缀,并添加到Configuration.loadedResources 集合中保存
configuration.addLoadedResource("namespace:" + namespace);
//调用M apperRegistry .addM apper ()方法,注册boundType 接口
configuration.addMapper(boundType);
}
}
}
public <T> void addMapper(Class<T> type) {
mapperRegistry.addMapper(type);
}
public <T> void addMapper(Class<T> type) {
//检测type 是否为接口
if (type.isInterface()) {
//检测是否已经加载过该接口
if (hasMapper(type)) {
throw new BindingException("Type " + type + " is already known to the MapperRegistry.");
}
boolean loadCompleted = false;
try {
//将Mapper 接口对应的Class 对象和MapperProxyFactory 对象添加到knownMappers 集合
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.
//XML 解析和注解的处理
MapperAnnotationBuilder parser = new MapperAnnotationBuilder(config, type);
parser.parse();
loadCompleted = true;
} finally {
if (!loadCompleted) {
knownMappers.remove(type);
}
}
}
}
/**
* 解析Mapper 接口中的注解信息
*/
public void parse() {
String resource = type.toString();
//检测是否已经加载过该接口
if (!configuration.isResourceLoaded(resource)) {
//检测是否加载过对应的映射配置文件,如果未加载,则创建XMLMapperBuilder 对象解析对应的 映射文件
loadXmlResource();
configuration.addLoadedResource(resource);
assistant.setCurrentNamespace(type.getName());
//解析@CacheNamespace i主解
parseCache();
//解析@CacheNamespaceRef 注解
parseCacheRef();
//遍历接口中定义的全部方法
for (Method method : type.getMethods()) {
if (!canHaveStatement(method)) {
continue;
}
if (getSqlCommandType(method) == SqlCommandType.SELECT && method.getAnnotation(ResultMap.class) == null) {
parseResultMap(method);
}
try {
parseStatement(method);
} catch (IncompleteElementException e) {
//如果解析过程出现IncompleteElementException异常,可能是引用了未解析的注解,
//这里将出现异常的方法添加到Configuration.incompleteMethods 集合中暂存,
//该集合是LinkedList< MethodResolver >类型
configuration.addIncompleteMethod(new MethodResolver(this, method));
}
}
}
//遍历Configuration.incompleteMethods 集合中记录的为解析的方法,并重新进行解析
parsePendingMethods();
}
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
public DefaultSqlSessionFactory(Configuration configuration) {
this.configuration = configuration;
}
@Override
public SqlSession openSession() {
return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}
/**
* 通过数据源获取数据库连接, 并创建Executor 对象以及DefaultSqlSession 对象
* @param execType
* @param level
* @param autoCommit
* @return
*/
private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
Transaction tx = null;
try {
//获取mybatis-config.xml 配置文件中配置的Environment 对象
final Environment environment = configuration.getEnvironment();
//获取的TransactionFactory 对象
final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
//创建Transaction 对象
tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
//根据配置创建Executor 对象
final Executor executor = configuration.newExecutor(tx, execType);
//创建DefaultSqlSession 对象
return new DefaultSqlSession(configuration, executor, autoCommit);
} catch (Exception e) {
// 关闭Transaction
closeTransaction(tx); // may have fetched a connection so lets call close()
throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
executorType = executorType == null ? defaultExecutorType : executorType;
executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
Executor executor;
//根据参数,选择合适的Executor 实现
if (ExecutorType.BATCH == executorType) {
executor = new BatchExecutor(this, transaction);
} else if (ExecutorType.REUSE == executorType) {
executor = new ReuseExecutor(this, transaction);
} else {
executor = new SimpleExecutor(this, transaction);
}
//根据配置决定是否开启二级缓存的功能
if (cacheEnabled) {
executor = new CachingExecutor(executor);
}
//创建Executor的代理对象
executor = (Executor) interceptorChain.pluginAll(executor);
return executor;
}
public Object pluginAll(Object target) {
//遍历interceptors 集合
for (Interceptor interceptor : interceptors) {
//调用
target = interceptor.plugin(target);
}
return target;
}
//决定是否触发intercept ()方法
default Object plugin(Object target) {
return Plugin.wrap(target, this);
}
public static Object wrap(Object target, Interceptor interceptor) {
//负责处理@Signature注解
Map<Class<?>, Set<Method>> signatureMap = getSignatureMap(interceptor);
//获取目标类型
Class<?> type = target.getClass();
//获取目标类型实现的接口
Class<?>[] interfaces = getAllInterfaces(type, signatureMap);
if (interfaces.length > 0) {
//使用JDK 动态代理的方式创建代理对象
return Proxy.newProxyInstance(
type.getClassLoader(),
interfaces,
new Plugin(target, interceptor, signatureMap));
}
return target;
}
@Override
public <T> T getMapper(Class<T> type) {
return configuration.getMapper(type, this);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
return mapperRegistry.getMapper(type, sqlSession);
}
public <T> T getMapper(Class<T> type, SqlSession sqlSession) {
//查找指定type 对应的MapperProxyFactory 对象
final MapperProxyFactory<T> mapperProxyFactory = (MapperProxyFactory<T>) knownMappers.get(type);
if (mapperProxyFactory == null) {
throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
}
try {
//创建实现了type 接口的代理对象
return mapperProxyFactory.newInstance(sqlSession);
} catch (Exception e) {
throw new BindingException("Error getting mapper instance. Cause: " + e, e);
}
}
public T newInstance(SqlSession sqlSession) {
//创建MapperProxy 对象,每次调用都会创建新的MapperProxy 对象
final MapperProxy<T> mapperProxy = new MapperProxy<>(sqlSession, mapperInterface, methodCache);
return newInstance(mapperProxy);
}
@SuppressWarnings("unchecked")
protected T newInstance(MapperProxy<T> mapperProxy) {
//创建实现了mapperinterface 接口的代理对象
return (T) Proxy.newProxyInstance(mapperInterface.getClassLoader(), new Class[] { mapperInterface }, mapperProxy);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
//如果目标方法继承自Object ,则直接调用目标方法
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
} else {
//从缓存中获取MapperMethod 对象,如缓存中没有,则创建新的MapperMethod 对象并添加到缓存中
return cachedInvoker(method).invoke(proxy, method, args, sqlSession);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
private MapperMethodInvoker cachedInvoker(Method method) throws Throwable {
try {
return methodCache.computeIfAbsent(method, m -> {
//如果是默认方法
if (m.isDefault()) {
try {
if (privateLookupInMethod == null) {
return new DefaultMethodInvoker(getMethodHandleJava8(method));
} else {
return new DefaultMethodInvoker(getMethodHandleJava9(method));
}
} catch (IllegalAccessException | InstantiationException | InvocationTargetException
| NoSuchMethodException e) {
throw new RuntimeException(e);
}
} else {
//创建MapperMethodInvoker
return new PlainMethodInvoker(new MapperMethod(mapperInterface, method, sqlSession.getConfiguration()));
}
});
} catch (RuntimeException re) {
Throwable cause = re.getCause();
throw cause == null ? re : cause;
}
}
public MapperMethod(Class<?> mapperInterface, Method method, Configuration config) {
// 记录了SQL 语句的名称和类型
this.command = new SqlCommand(config, mapperInterface, method);
// Mapper 接口中对应方法的相关信息
this.method = new MethodSignature(config, mapperInterface, method);
}
public SqlCommand(Configuration configuration, Class<?> mapperInterface, Method method) {
final String methodName = method.getName();
final Class<?> declaringClass = method.getDeclaringClass();
MappedStatement ms = resolveMappedStatement(mapperInterface, methodName, declaringClass,
configuration);
if (ms == null) {
//处理@ Flush i主解
if (method.getAnnotation(Flush.class) != null) {
name = null;
type = SqlCommandType.FLUSH;
} else {
throw new BindingException("Invalid bound statement (not found): "
+ mapperInterface.getName() + "." + methodName);
}
} else {
//初始化name 和type
name = ms.getId();
type = ms.getSqlCommandType();
if (type == SqlCommandType.UNKNOWN) {
throw new BindingException("Unknown execution method for: " + name);
}
}
}
private MappedStatement resolveMappedStatement(Class<?> mapperInterface, String methodName,
Class<?> declaringClass, Configuration configuration) {
// SQL 语句的名称是由Mapper 接口的名称与对应的方法名称组成的
String statementId = mapperInterface.getName() + "." + methodName;
//检测是否有该名称的SQL 语句
if (configuration.hasStatement(statementId)) {
//从Configuration.mappedStatements集合中查找对应的MappedStatement对象
return configuration.getMappedStatement(statementId);
} else if (mapperInterface.equals(declaringClass)) {
return null;
}
//如果指定方法是在父接口中定义的, 则在此进行继承结构的处理
for (Class<?> superInterface : mapperInterface.getInterfaces()) {
if (declaringClass.isAssignableFrom(superInterface)) {
MappedStatement ms = resolveMappedStatement(superInterface, methodName,
declaringClass, configuration);
if (ms != null) {
return ms;
}
}
}
return null;
}
}
public MethodSignature(Configuration configuration, Class<?> mapperInterface, Method method) {
//解析方法的返回值类型
Type resolvedReturnType = TypeParameterResolver.resolveReturnType(method, mapperInterface);
if (resolvedReturnType instanceof Class<?>) {
this.returnType = (Class<?>) resolvedReturnType;
} else if (resolvedReturnType instanceof ParameterizedType) {
this.returnType = (Class<?>) ((ParameterizedType) resolvedReturnType).getRawType();
} else {
this.returnType = method.getReturnType();
}
//初始化returnsVoid 、returnsMany 、returnsCursor 、map Key 、returnsMap 等字段
this.returnsVoid = void.class.equals(this.returnType);
this.returnsMany = configuration.getObjectFactory().isCollection(this.returnType) || this.returnType.isArray();
this.returnsCursor = Cursor.class.equals(this.returnType);
this.returnsOptional = Optional.class.equals(this.returnType);
//若MethodSignature 对应方法的返回位是Map 且指定了@ Map Key注解,则使用getMapKey ()方法处理
this.mapKey = getMapKey(method);
this.returnsMap = this.mapKey != null;
//初始化rowBoundsindex 和resultHandlerindex 字段
this.rowBoundsIndex = getUniqueParamIndex(method, RowBounds.class);
this.resultHandlerIndex = getUniqueParamIndex(method, ResultHandler.class);
//创建ParamNameResolver 对象
this.paramNameResolver = new ParamNameResolver(configuration, method);
}
//查找指定类型的参数在参数列表中的位置
private Integer getUniqueParamIndex(Method method, Class<?> paramType) {
Integer index = null;
final Class<?>[] argTypes = method.getParameterTypes();
for (int i = 0; i < argTypes.length; i++) {
if (paramType.isAssignableFrom(argTypes[i])) {
//记录paramType 类型参数在参数列表中的位置索引
if (index == null) {
index = i;
} else {
// RowBounds 和ResultHandler 类型的参数只能有一个,不能重复出现
throw new BindingException(method.getName() + " cannot have multiple " + paramType.getSimpleName() + " parameters");
}
}
}
return index;
}
public boolean returnsOptional() {
return returnsOptional;
}
//查找指定类型的参数在参数列表中的位置
private Integer getUniqueParamIndex(Method method, Class<?> paramType) {
Integer index = null;
final Class<?>[] argTypes = method.getParameterTypes();
for (int i = 0; i < argTypes.length; i++) {
if (paramType.isAssignableFrom(argTypes[i])) {
//记录paramType 类型参数在参数列表中的位置索引
if (index == null) {
index = i;
} else {
// RowBounds 和ResultHandler 类型的参数只能有一个,不能重复出现
throw new BindingException(method.getName() + " cannot have multiple " + paramType.getSimpleName() + " parameters");
}
}
}
return index;
}
public ParamNameResolver(Configuration config, Method method) {
this.useActualParamName = config.isUseActualParamName();
//获取参数列表中每个参数的类型
final Class<?>[] paramTypes = method.getParameterTypes();
//获取参数列表上的注解
final Annotation[][] paramAnnotations = method.getParameterAnnotations();
//该集合用于记录参数索引与参数名称的对应关系
final SortedMap<Integer, String> map = new TreeMap<>();
int paramCount = paramAnnotations.length;
// get names from @Param annotations
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
//如参数是RowBounds 类型或ResultHandler 类型,跳过对该参数的分析
if (isSpecialParameter(paramTypes[paramIndex])) {
// skip special parameters
continue;
}
String name = null;
// 遥历该参数对应的i主解集合
for (Annotation annotation : paramAnnotations[paramIndex]) {
// @Param出现过一次,就将hasParamAnnotation 初始化为true
if (annotation instanceof Param) {
hasParamAnnotation = true;
//获取自Param注解指定的参数名称
name = ((Param) annotation).value();
break;
}
}
if (name == null) {
// @Param was not specified.
//该参数没有对应的@Param注解,则根据配置决定是否使用参数实际名称作为其名称
if (useActualParamName) {
name = getActualParamName(method, paramIndex);
}
if (name == null) {
// use the parameter index as the name ("0", "1", ...)
// gcode issue #71
//使用参数的索引作为其名称
name = String.valueOf(map.size());
}
}
// 记录到map 中保存
map.put(paramIndex, name);
}
// 初始化names 集合
names = Collections.unmodifiableSortedMap(map);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args, SqlSession sqlSession) throws Throwable {
return mapperMethod.execute(sqlSession, args);
}
//根据SQL 语句的类型调用SqI Session 对应的方法完成数据库操作。
public Object execute(SqlSession sqlSession, Object[] args) {
Object result;
//根据SQL 语句的类型调用SqlSession 对应的方法
switch (command.getType()) {
case INSERT: {
//使用ParamNameResolver处理args []数组(用户传入的实参列表),将用户传入的实参与指定参数名称关联起来
Object param = method.convertArgsToSqlCommandParam(args);
//调用SqlSession.insert ()方法, rowCountResult ()方法会根据method 字段中记录的方法的 返回值类型对结果进行转换
result = rowCountResult(sqlSession.insert(command.getName(), param));
break;
}
case UPDATE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.update(command.getName(), param));
break;
}
case DELETE: {
Object param = method.convertArgsToSqlCommandParam(args);
result = rowCountResult(sqlSession.delete(command.getName(), param));
break;
}
case SELECT:
//处理返回值为void 且ResultSet 通过ResultHandler 处理的方法
if (method.returnsVoid() && method.hasResultHandler()) {
executeWithResultHandler(sqlSession, args);
result = null;
} else if (method.returnsMany()) {
//处理返回值为集合或数组的方法
result = executeForMany(sqlSession, args);
} else if (method.returnsMap()) {
//处理返回值为Map 的方法
result = executeForMap(sqlSession, args);
} else if (method.returnsCursor()) {
// 处理返回值为Curs or 的方法
result = executeForCursor(sqlSession, args);
} else {
//处理返回值为单一对象的方法
Object param = method.convertArgsToSqlCommandParam(args);
result = sqlSession.selectOne(command.getName(), param);
if (method.returnsOptional()
&& (result == null || !method.getReturnType().equals(result.getClass()))) {
result = Optional.ofNullable(result);
}
}
break;
case FLUSH:
result = sqlSession.flushStatements();
break;
default:
throw new BindingException("Unknown execution method for: " + command.getName());
}
if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
throw new BindingException("Mapper method '" + command.getName()
+ " attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
}
return result;
}
//负责将args []数纽( 用户传入的实参列表)转换成SQL 语句对应的参数列表,
public Object convertArgsToSqlCommandParam(Object[] args) {
return paramNameResolver.getNamedParams(args);
}
public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
// 无参数,返回null
if (args == null || paramCount == 0) {
return null;
} else if (!hasParamAnnotation && paramCount == 1) {
// 未使用@Param且只有一个参数
Object value = args[names.firstKey()];
return wrapToMapIfCollection(value, useActualParamName ? names.get(0) : null);
} else {
//处理使用@Paramd主解指定了参数名称或有多个参数的情况
// param这个Map中记录了参数名称与实参之间的对应关系。ParamMap继承了HashMap ,如果向
// ParamMap 中添加已经存在的key ,会报错,其他行为与HashMap 相同
final Map<String, Object> param = new ParamMap<>();
int i = 0;
for (Map.Entry<Integer, String> entry : names.entrySet()) {
//将参数名与实参对应关系记录到pa ram 中
param.put(entry.getValue(), args[entry.getKey()]);
// add generic param names (param1, param2, ...)
// 下面是为参数创建” param+索引”格式的默认参数名称,例如: paraml , param2等,并添加到param 集合中
final String genericParamName = GENERIC_NAME_PREFIX + (i + 1);
// ensure not to overwrite parameter named with @Param
//如@Param主解指定的参数名称就是” param+索引”格式的,则不需要再添加
if (!names.containsValue(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
}
@Override
public <T> T selectOne(String statement, Object parameter) {
// Popular vote was to return null on 0 results and throw exception on too many.
List<T> list = this.selectList(statement, parameter);
if (list.size() == 1) {
return list.get(0);
} else if (list.size() > 1) {
throw new TooManyResultsException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
} else {
return null;
}
}
@Override
public <E> List<E> selectList(String statement, Object parameter) {
return this.selectList(statement, parameter, RowBounds.DEFAULT);
}
@Override
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
try {
MappedStatement ms = configuration.getMappedStatement(statement);
return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
} finally {
ErrorContext.instance().reset();
}
}
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
//获取BoundSql 对象
BoundSql boundSql = ms.getBoundSql(parameter);
// 创建CacheKey 对象
CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
// 调用query ()的另一个重载,继续后续处理
return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
public BoundSql getBoundSql(Object parameterObject) {
BoundSql boundSql = sqlSource.getBoundSql(parameterObject);
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
if (parameterMappings == null || parameterMappings.isEmpty()) {
boundSql = new BoundSql(configuration, boundSql.getSql(), parameterMap.getParameterMappings(), parameterObject);
}
// check for nested result maps in parameter mappings (issue #30)
for (ParameterMapping pm : boundSql.getParameterMappings()) {
String rmId = pm.getResultMapId();
if (rmId != null) {
ResultMap rm = configuration.getResultMap(rmId);
if (rm != null) {
hasNestedResultMaps |= rm.hasNestedResultMaps();
}
}
}
return boundSql;
}
@Override
public CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql) {
//检测当前Executor 是否已经关闭
if (closed) {
throw new ExecutorException("Executor was closed.");
}
//创建CacheKey 对象
CacheKey cacheKey = new CacheKey();
//将MappedStatement 的id 添加到Cache Key 对象中
cacheKey.update(ms.getId());
//将off set 添加到CacheKey 对象中
cacheKey.update(rowBounds.getOffset());
//将limit 添加到CacheKey 对象中
cacheKey.update(rowBounds.getLimit());
//将SQL 语句添加到CacheKey 对象中
cacheKey.update(boundSql.getSql());
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
TypeHandlerRegistry typeHandlerRegistry = ms.getConfiguration().getTypeHandlerRegistry();
// mimic DefaultParameterHandler logic
//获取用户传入的实参,并添加.f1J CacheKey 对象中
for (ParameterMapping parameterMapping : parameterMappings) {
//过滤输出类型的参数
if (parameterMapping.getMode() != ParameterMode.OUT) {
Object value;
String propertyName = parameterMapping.getProperty();
if (boundSql.hasAdditionalParameter(propertyName)) {
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
value = parameterObject;
} else {
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
//将实参添加到CacheKey 对象中
cacheKey.update(value);
}
}
//如果Environment 的id 不为空,则将其添加到CacheKey 中
if (configuration.getEnvironment() != null) {
// issue #176
cacheKey.update(configuration.getEnvironment().getId());
}
return cacheKey;
}
public void update(Object object) {
int baseHashCode = object == null ? 1 : ArrayUtil.hashCode(object);
count++;
checksum += baseHashCode;
baseHashCode *= count;
hashcode = multiplier * hashcode + baseHashCode;
//将object 添加到updateList 集合中
updateList.add(object);
}
@Override
public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
//检测当前Executor 是否已经关闭
if (closed) {
throw new ExecutorException("Executor was closed.");
}
if (queryStack == 0 && ms.isFlushCacheRequired()) {
//非嵌套查询,并且< select >节点配置的flushCache 属性为true 时,才会清空一级缓存
// flushCache 配置项是影响一级缓存中结果对象存活时长的第一个方面
clearLocalCache();
}
List<E> list;
try {
//培加查询层数
queryStack++;
//查询一级缓存
list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
if (list != null) {
//针对存储过程调用的处理, 其功能是: 在一级缓存命中时,获取缓存中保存的输出类型参数,并设置到用户传入的实参( parameter )对象中
handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
} else {
//其中会调用doQuery ()方法完成数据库查询,并得到映射后的结果对象
list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
}
} finally {
//当前查询完成,查询层数减少
queryStack--;
}
if (queryStack == 0) {
//延迟加载
// 在最外层的查询结束时,所有嵌套查询也已经完成,相关缓存项也已经完全加载,所以在这里可以
//触发DeferredLoad 加载一级缓存中记录的嵌套查询的结果对象
for (DeferredLoad deferredLoad : deferredLoads) {
deferredLoad.load();
}
// issue #601
//加裁完成后, 清空deferredLoads 集合
deferredLoads.clear();
if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) {
// issue #482
//根据localCacheScope 配置决定是否清空一级缓存,localCacheScope 配置是影响一级缓
//存中结果对象存活时长的第二个方面
clearLocalCache();
}
}
return list;
}
private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException {
List<E> list;
// 在缓存中添加占位符
localCache.putObject(key, EXECUTION_PLACEHOLDER);
try {
//调用doQuery ()方法(抽象方法),完成数据库查询操作,并返回结果对象
list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
} finally {
//删除占位符
localCache.removeObject(key);
}
//将真正的结果对象添加到一级缓存中
localCache.putObject(key, list);
//是否为存储过程调用
if (ms.getStatementType() == StatementType.CALLABLE) {
//缓存输出类型的参数
localOutputParameterCache.putObject(key, parameter);
}
return list;
}
@Override
public <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) throws SQLException {
Statement stmt = null;
try {
//获取配置对象
Configuration configuration = ms.getConfiguration();
// 创建StatementHandler 对象,实际返回的是RoutingStatementHandler 对象,
StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
//完成Statement 的创建和初始化,该方法首先会调用StatementHandler.prepare ()方法创建
//Statement 对象, 然后调用StatementH andler. parameterize ()方法处理占位符
stmt = prepareStatement(handler, ms.getStatementLog());
//调用StatementHandler.query ()方法,执行SQL 语句,并通过ResultSetHandler 完成结果集的映射
return handler.query(stmt, resultHandler);
} finally {
//关闭Statement对象
closeStatement(stmt);
}
}
public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) {
//利用策略模式创建不同的StatementHandler
StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
//拦截器代理
statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
return statementHandler;
}
private Statement prepareStatement(StatementHandler handler, Log statementLog) throws SQLException {
Statement stmt;
Connection connection = getConnection(statementLog);
//创建Statement 对象
stmt = handler.prepare(connection, transaction.getTimeout());
//处理占位符
handler.parameterize(stmt);
return stmt;
}
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
return delegate.prepare(connection, transactionTimeout);
}
@Override
public Statement prepare(Connection connection, Integer transactionTimeout) throws SQLException {
ErrorContext.instance().sql(boundSql.getSql());
Statement statement = null;
try {
//实例化statement
statement = instantiateStatement(connection);
setStatementTimeout(statement, transactionTimeout);
setFetchSize(statement);
return statement;
} catch (SQLException e) {
closeStatement(statement);
throw e;
} catch (Exception e) {
closeStatement(statement);
throw new ExecutorException("Error preparing statement. Cause: " + e, e);
}
}
@Override
protected Statement instantiateStatement(Connection connection) throws SQLException {
//获取待执行的SQL 语句
String sql = boundSql.getSql();
// 根据MappedStatement.keyGenerator 字段的值,创建PreparedStatement 对象
if (mappedStatement.getKeyGenerator() instanceof Jdbc3KeyGenerator) {
String[] keyColumnNames = mappedStatement.getKeyColumns();
if (keyColumnNames == null) {
// 返回数据库生成的主键
return connection.prepareStatement(sql, PreparedStatement.RETURN_GENERATED_KEYS);
} else {
// 在insert 语句执行完成之后,会将key ColumnNames 指定的列返回
return connection.prepareStatement(sql, keyColumnNames);
}
} else if (mappedStatement.getResultSetType() == ResultSetType.DEFAULT) {
// 创建普通的PreparedSta tement 对象
return connection.prepareStatement(sql);
} else {
// 设置结果集是否可以滚动以及其游标是否可以上下移动,设置结果集是否可更新
return connection.prepareStatement(sql, mappedStatement.getResultSetType().getValue(), ResultSet.CONCUR_READ_ONLY);
}
}
@Override
public void parameterize(Statement statement) throws SQLException {
delegate.parameterize(statement);
}
@Override
public void parameterize(Statement statement) throws SQLException {
parameterHandler.setParameters((PreparedStatement) statement);
}
@Override
public void setParameters(PreparedStatement ps) {
ErrorContext.instance().activity("setting parameters").object(mappedStatement.getParameterMap().getId());
// 取出sql 中的参数映射列表
List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
// 检测parameterMappings 集合是否为空
if (parameterMappings != null) {
for (int i = 0; i < parameterMappings.size(); i++) {
ParameterMapping parameterMapping = parameterMappings.get(i);
//过滤掉存储过程中的输出参数
if (parameterMapping.getMode() != ParameterMode.OUT) {
//记录绑定的实参
Object value;
//获取参数名称
String propertyName = parameterMapping.getProperty();
//获取对应的实参位
if (boundSql.hasAdditionalParameter(propertyName)) { // issue #448 ask first for additional params
value = boundSql.getAdditionalParameter(propertyName);
} else if (parameterObject == null) {
//整个实参为空
value = null;
} else if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {
// 实参可以直接通过TypeHandler 转换成JdbcType
value = parameterObject;
} else {
//获取对象中相应的属性值或查找Map对象中值
MetaObject metaObject = configuration.newMetaObject(parameterObject);
value = metaObject.getValue(propertyName);
}
//获取ParameterMapping 中设置的TypeHandler 对象
TypeHandler typeHandler = parameterMapping.getTypeHandler();
JdbcType jdbcType = parameterMapping.getJdbcType();
if (value == null && jdbcType == null) {
jdbcType = configuration.getJdbcTypeForNull();
}
try {
//通过TypeHandler . setParametera ()方法会调用PreparedStatement.set *()方法 为SQL 语句绑定相应的实参,
typeHandler.setParameter(ps, i + 1, value, jdbcType);
} catch (TypeException | SQLException e) {
throw new TypeException("Could not set parameters for mapping: " + parameterMapping + ". Cause: " + e, e);
}
}
}
}
}
public boolean hasTypeHandler(Class<?> javaType) {
return hasTypeHandler(javaType, null);
}
public boolean hasTypeHandler(Class<?> javaType, JdbcType jdbcType) {
return javaType != null && getTypeHandler((Type) javaType, jdbcType) != null;
}
/**
* 根据指定的Java类型和JdbcType 类型查找相应的TypeHandler对象,
* @param type
* @return
*/
private <T> TypeHandler<T> getTypeHandler(Type type, JdbcType jdbcType) {
if (ParamMap.class.equals(type)) {
return null;
}
//查找(或初始化) Java 类型对应的TypeHandler集合
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = getJdbcHandlerMap(type);
TypeHandler<?> handler = null;
if (jdbcHandlerMap != null) {
// 根据JdbcType 类型查找TypeHandler 对象
handler = jdbcHandlerMap.get(jdbcType);
if (handler == null) {
handler = jdbcHandlerMap.get(null);
}
if (handler == null) {
// #591
//如果jdbcHandlerMap 只注册了一个Type Handler ,则使用此TypeHandler 对象
handler = pickSoleHandler(jdbcHandlerMap);
}
}
// type drives generics here
return (TypeHandler<T>) handler;
}
private Map<JdbcType, TypeHandler<?>> getJdbcHandlerMap(Type type) {
//查找指定Java 类型对应的TypeHandler 集合
Map<JdbcType, TypeHandler<?>> jdbcHandlerMap = typeHandlerMap.get(type);
//检测是否为空集合标识
if (NULL_TYPE_HANDLER_MAP.equals(jdbcHandlerMap)) {
return null;
}
//初始化指定Java 类型的T ypeHandler 集合
if (jdbcHandlerMap == null && type instanceof Class) {
Class<?> clazz = (Class<?>) type;
//枚举类型的处理
if (Enum.class.isAssignableFrom(clazz)) {
Class<?> enumClass = clazz.isAnonymousClass() ? clazz.getSuperclass() : clazz;
jdbcHandlerMap = getJdbcHandlerMapForEnumInterfaces(enumClass, enumClass);
if (jdbcHandlerMap == null) {
register(enumClass, getInstance(enumClass, defaultEnumTypeHandler));
return typeHandlerMap.get(enumClass);
}
} else {
//查找父类对应的TypeHandler 集合,并作为初始集合
jdbcHandlerMap = getJdbcHandlerMapForSuperclass(clazz);
}
}
typeHandlerMap.put(type, jdbcHandlerMap == null ? NULL_TYPE_HANDLER_MAP : jdbcHandlerMap);
return jdbcHandlerMap;
}
@Override
public void setParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {
if (parameter == null) {
if (jdbcType == null) {
throw new TypeException("JDBC requires that the JdbcType must be specified for all nullable parameters.");
}
try {
ps.setNull(i, jdbcType.TYPE_CODE);
} catch (SQLException e) {
throw new TypeException("Error setting null for parameter #" + i + " with JdbcType " + jdbcType + " . "
+ "Try setting a different JdbcType for this parameter or a different jdbcTypeForNull configuration property. "
+ "Cause: " + e, e);
}
} else {
try {
setNonNullParameter(ps, i, parameter, jdbcType);
} catch (Exception e) {
throw new TypeException("Error setting non null for parameter #" + i + " with JdbcType " + jdbcType + " . "
+ "Try setting a different JdbcType for this parameter or a different configuration property. "
+ "Cause: " + e, e);
}
}
}
@Override
public void setNonNullParameter(PreparedStatement ps, int i, Integer parameter, JdbcType jdbcType)
throws SQLException {
ps.setInt(i, parameter);
}
@Override
public <E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException {
PreparedStatement ps = (PreparedStatement) statement;
ps.execute();
return resultSetHandler.handleResultSets(ps);
}
/**
* 处理Statement 、PreparedStatement 产生的结果集,还可以处理
* Callab leStatement 调用存储过程产生的多结果集。
* @param stmt
* @return
* @throws SQLException
*/
@Override
public List<Object> handleResultSets(Statement stmt) throws SQLException {
ErrorContext.instance().activity("handling results").object(mappedStatement.getId());
//保存映射结果集得到的结果对象
final List<Object> multipleResults = new ArrayList<>();
int resultSetCount = 0;
// 获取第一个ResultSet 对象,可能存在多个ResultSet ,这里只获取第一个ResultSet
ResultSetWrapper rsw = getFirstResultSet(stmt);
List<ResultMap> resultMaps = mappedStatement.getResultMaps();
int resultMapCount = resultMaps.size();
validateResultMapsCount(rsw, resultMapCount);
//结果集不为空,则resultMaps 集合不能为空,
//遍历resultMaps 集合
while (rsw != null && resultMapCount > resultSetCount) {
//获取该结果集对应的ResultMap 对象
ResultMap resultMap = resultMaps.get(resultSetCount);
//根据ResultMap 中定义的映射规则对ResultSet 进行映射, 并将映射的结果对象添加到 multipleResults 集合中保存
//将未解析的结果集保存nextResultMaps暂存
handleResultSet(rsw, resultMap, multipleResults, null);
//获取下一个结果集
rsw = getNextResultSet(stmt);
//清空nestedResultObjects 集合
cleanUpAfterHandlingResultSet();
// 递增resultSetCount
resultSetCount++;
}
//获取MappedStatement.resultSets属性。该属性仅对多结果集的情况适用,该属性将列出语句执
//行后返回的结果集,并给每个结果集一个名称,名称是逗号分隔的
String[] resultSets = mappedStatement.getResultSets();
if (resultSets != null) {
while (rsw != null && resultSetCount < resultSets.length) {
//根据resultSet 的名称,获取未处理的ResultMapping
ResultMapping parentMapping = nextResultMaps.get(resultSets[resultSetCount]);
if (parentMapping != null) {
//获取映射该结果集要使用的ResultMap 对象
String nestedResultMapId = parentMapping.getNestedResultMapId();
ResultMap resultMap = configuration.getResultMap(nestedResultMapId);
//根据ResultMap 对象映射结果集
handleResultSet(rsw, resultMap, null, parentMapping);
}
// 获取下一个结果集
rsw = getNextResultSet(stmt);
// 清空nestedResultObjects 集合
cleanUpAfterHandlingResultSet();
// 递增resultSetCount
resultSetCount++;
}
}
return collapseSingleResultList(multipleResults);
}
@Override
public void putObject(Object key, Object value) {
cache.put(key, value);
}
@Override
public <E> List<E> query(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException {
//步骤1 :获取BoundSql 对象,
BoundSql boundSql = ms.getBoundSql(parameterObject);
//创建CacheKey 对象
CacheKey key = createCacheKey(ms, parameterObject, rowBounds, boundSql);
return query(ms, parameterObject, rowBounds, resultHandler, key, boundSql);
}
public static MetaClass forClass(Class<?> type, ReflectorFactory reflectorFactory) {
return new MetaClass(type, reflectorFactory);
}
private MetaClass(Class<?> type, ReflectorFactory reflectorFactory) {
this.reflectorFactory = reflectorFactory;
this.reflector = reflectorFactory.findForClass(type);
}
@Override
public Reflector findForClass(Class<?> type) {
//检测是否开启缓存
if (classCacheEnabled) {
// synchronized (type) removed see issue #461
return reflectorMap.computeIfAbsent(type, Reflector::new);
} else {
//未开启缓存,则直接创建并返回Reflector对象
return new Reflector(type);
}
}
public Reflector(Class<?> clazz) {
type = clazz;
//查找clazz 的默认构造方法(无参构造方法)
addDefaultConstructor(clazz);
//处理clazz 中的getter 方法,填充getMethods 集合和getTypes 集合
addGetMethods(clazz);
//处理clazz 中的set ter 方法,填充setMethods 集合和set Types 集合
addSetMethods(clazz);
//处理没有g etter I setter 方法的字段
addFields(clazz);
//根据getMethodslsetMethods 集合,初始化可读/写属性的名称集合
readablePropertyNames = getMethods.keySet().toArray(new String[0]);
writablePropertyNames = setMethods.keySet().toArray(new String[0]);
//初始化caseinsensitivePropertyMap 集合,其中记录了所有大写格式的属性名称
for (String propName : readablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
for (String propName : writablePropertyNames) {
caseInsensitivePropertyMap.put(propName.toUpperCase(Locale.ENGLISH), propName);
}
}
private void addDefaultConstructor(Class<?> clazz) {
//获取所有声明构造
Constructor<?>[] constructors = clazz.getDeclaredConstructors();
Arrays.stream(constructors).
//过滤默认构造
filter(constructor -> constructor.getParameterTypes().length == 0)
//查询所有
.findAny()
//设置默认构造
.ifPresent(constructor -> this.defaultConstructor = constructor);
}
/**
* 填充getMethods 集合和getTypes 集合
* @param clazz
*/
private void addGetMethods(Class<?> clazz) {
Map<String, List<Method>> conflictingGetters = new HashMap<>();
//获取指定类以及其父类和接口中定义的方法
Method[] methods = getClassMethods(clazz);
//对get方法过滤
Arrays.stream(methods).filter(m ->
//JavaBean 中getter 方法的方法名长度大于3 且必须以” get ” 开头
m.getParameterTypes().length == 0 && PropertyNamer.isGetter(m.getName()))
.forEach(m ->
//记录到conflictingGetters集合中
addMethodConflict(conflictingGetters,
//获取对应的属性名称
PropertyNamer.methodToProperty(m.getName()), m));
//对方法同名返回值不一样的处理
resolveGetterConflicts(conflictingGetters);
}
private Method[] getClassMethods(Class<?> clazz) {
//用于记录指定类中定义的全部方法的唯一签名以及对应的Meth od 对象
Map<String, Method> uniqueMethods = new HashMap<>();
Class<?> currentClass = clazz;
while (currentClass != null && currentClass != Object.class) {
//记录currentClass 这个类中定义的全部方法.桥方法除外
addUniqueMethods(uniqueMethods, currentClass.getDeclaredMethods());
// we also need to look for interface methods -
// because the class may be abstract
//记录接口中定义的方法
Class<?>[] interfaces = currentClass.getInterfaces();
for (Class<?> anInterface : interfaces) {
addUniqueMethods(uniqueMethods, anInterface.getMethods());
}
//获取父类,继续while 循环
currentClass = currentClass.getSuperclass();
}
Collection<Method> methods = uniqueMethods.values();
return methods.toArray(new Method[0]);
}
private void addUniqueMethods(Map<String, Method> uniqueMethods, Method[] methods) {
for (Method currentMethod : methods) {
//过滤桥接方法,也就是为了兼容泛型,重新定义了一个方法,调用原来的方法,定位桥
if (!currentMethod.isBridge()) {
//方法得到的方法签名是全局唯一的,可以作为该方法 的唯一标识
String signature = getSignature(currentMethod);
// check to see if the method is already known
// if it is known, then an extended class must have
// overridden a method
//检测是否在子类中已经添加过该方法,如果在子类中已经添加过,无须再向uniqueMethods 集合中添加该方法了
if (!uniqueMethods.containsKey(signature)) {
//记录该签名和方法的对应关系
uniqueMethods.put(signature, currentMethod);
}
}
}
}
private String getSignature(Method method) {
//格式 org.apache.ibatis.cache.Cache#getCache:java.lang.String
StringBuilder sb = new StringBuilder();
Class<?> returnType = method.getReturnType();
if (returnType != null) {
sb.append(returnType.getName()).append('#');
}
sb.append(method.getName());
Class<?>[] parameters = method.getParameterTypes();
for (int i = 0; i < parameters.length; i++) {
sb.append(i == 0 ? ':' : ',').append(parameters[i].getName());
}
return sb.toString();
}
//检测方法是否为getter方法
public static boolean isGetter(String name) {
return (name.startsWith("get") && name.length() > 3) || (name.startsWith("is") && name.length() > 2);
}
//将方法名转换成属性名
public static String methodToProperty(String name) {
if (name.startsWith("is")) {
name = name.substring(2);
} else if (name.startsWith("get") || name.startsWith("set")) {
name = name.substring(3);
} else {
throw new ReflectionException("Error parsing property name '" + name + "'. Didn't start with 'is', 'get' or 'set'.");
}
if (name.length() == 1 || (name.length() > 1 && !Character.isUpperCase(name.charAt(1)))) {
name = name.substring(0, 1).toLowerCase(Locale.ENGLISH) + name.substring(1);
}
return name;
}
private void addMethodConflict(Map<String, List<Method>> conflictingMethods, String name, Method method) {
//排除序列化id的get
if (isValidPropertyName(name)) {
// key:方法名
//value:方法
List<Method> list = conflictingMethods.computeIfAbsent(name, k -> new ArrayList<>());
list.add(method);
}
}
private void resolveGetterConflicts(Map<String, List<Method>> conflictingGetters) {
for (Entry<String, List<Method>> entry : conflictingGetters.entrySet()) {
Method winner = null;
String propName = entry.getKey();
boolean isAmbiguous = false;
for (Method candidate : entry.getValue()) {
if (winner == null) {
winner = candidate;
continue;
}
//同一属性名称存在多个getter方法,则需要比较这些getter方法的返回,选择getter方法
//迭代过程中的临时变量,用于记录迭代到目前为止,最适合作为getter 方法的Method
Class<?> winnerType = winner.getReturnType();
Class<?> candidateType = candidate.getReturnType();
if (candidateType.equals(winnerType)) {
//对boolean处理
if (!boolean.class.equals(candidateType)) {
isAmbiguous = true;
break;
} else if (candidate.getName().startsWith("is")) {
winner = candidate;
}
} else if (candidateType.isAssignableFrom(winnerType)) {
// OK getter type is descendant
//当前最适合的方法的返回佳是当前方法返回的子类,什么都不做,当前最适合的方法 依然不变
} else if (winnerType.isAssignableFrom(candidateType)) {
//当前方法的返回位是当前最适合的方法的返回值的子类,更新临时交量getter,当前的getter 方法成为最适合的getter 方法
winner = candidate;
} else {
//返回值相同,二义性,抛出异常
isAmbiguous = true;
break;
}
}
//添加到getMethods 集合并填充get Types 集合
addGetMethod(propName, winner, isAmbiguous);
}
}
private void addGetMethod(String name, Method method, boolean isAmbiguous) {
MethodInvoker invoker = isAmbiguous
? new AmbiguousMethodInvoker(method, MessageFormat.format(
"Illegal overloaded getter method with ambiguous type for property ''{0}'' in class ''{1}''. This breaks the JavaBeans specification and can cause unpredictable results.",
name, method.getDeclaringClass().getName()))
:
//将属性名以及对应的Methodinvoker对象添加getMethods集合中,
new MethodInvoker(method);
getMethods.put(name, invoker);
//获取返回值的Type
Type returnType = TypeParameterResolver.resolveReturnType(method, type);
//将属性名称及其getter方法的返回位类型添加到getTypes集合中保存
getTypes.put(name, typeToClass(returnType));
}
public static Type resolveReturnType(Method method, Type srcType) {
//获取方法返回值
Type returnType = method.getGenericReturnType();
Class<?> declaringClass = method.getDeclaringClass();
return resolveType(returnType, srcType, declaringClass);
}
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
if (type instanceof TypeVariable) {
return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
} else if (type instanceof ParameterizedType) {
return resolveParameterizedType(
//待解析的ParameterizedType 类型;
(ParameterizedType) type,
//解析操作的起始类型testType.SubClassA
srcType,
//定义该字段或方法的类的Class 对象ClassA
declaringClass);
} else if (type instanceof GenericArrayType) {
//根据数组元素类型选择合适的方法进行解析
return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
} else {
return type;//Class 类型
}
}
private void addSetMethods(Class<?> clazz) {
Map<String, List<Method>> conflictingSetters = new HashMap<>();
Method[] methods = getClassMethods(clazz);
Arrays.stream(methods).filter(m -> m.getParameterTypes().length == 1 && PropertyNamer.isSetter(m.getName()))
.forEach(m -> addMethodConflict(conflictingSetters, PropertyNamer.methodToProperty(m.getName()), m));
resolveSetterConflicts(conflictingSetters);
}
/**
* 添加字段
* @param clazz
*/
private void addFields(Class<?> clazz) {
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
//当setMethods 集合不包含同名属性时,将其记录到setMethods 集合和set Types 集合
if (!setMethods.containsKey(field.getName())) {
// issue #379 - removed the check for final because JDK 1.5 allows
// modification of final fields through reflection (JSR-133). (JGB)
// pr #16 - final static can only be set by the classloader
int modifiers = field.getModifiers();
//过滤掉final和static 修饰的字段
if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers))) {
addSetField(field);
}
}
//当getMethods 集合中不包含同名属性时,将其记录到getMethods 集合和getTypes 集合
if (!getMethods.containsKey(field.getName())) {
addGetField(field);
}
}
if (clazz.getSuperclass() != null) {
//处理父类中定义的字段
addFields(clazz.getSuperclass());
}
}
private void addSetField(Field field) {
if (isValidPropertyName(field.getName())) {
setMethods.put(field.getName(), new SetFieldInvoker(field));
Type fieldType = TypeParameterResolver.resolveFieldType(field, type);
setTypes.put(field.getName(), typeToClass(fieldType));
}
}
private void addGetField(Field field) {
if (isValidPropertyName(field.getName())) {
getMethods.put(field.getName(), new GetFieldInvoker(field));
Type fieldType = TypeParameterResolver.resolveFieldType(field, type);
getTypes.put(field.getName(), typeToClass(fieldType));
}
}
/*
srcType泛型应用到父类泛型上,从而确定泛型
*/
public static Type resolveFieldType(Field field, Type srcType) {
//获取字段的声明类型
Type fieldType = field.getGenericType();
//获取字段定义所在的类的Class 对象
Class<?> declaringClass = field.getDeclaringClass();
return resolveType(
//Map
fieldType,
//testType.SubClassA
srcType,
//ClassA
declaringClass);
}
private static Type resolveType(Type type, Type srcType, Class<?> declaringClass) {
if (type instanceof TypeVariable) {
return resolveTypeVar((TypeVariable<?>) type, srcType, declaringClass);
} else if (type instanceof ParameterizedType) {
return resolveParameterizedType(
//待解析的ParameterizedType 类型;
(ParameterizedType) type,
//解析操作的起始类型testType.SubClassA
srcType,
//定义该字段或方法的类的Class 对象ClassA
declaringClass);
} else if (type instanceof GenericArrayType) {
//根据数组元素类型选择合适的方法进行解析
return resolveGenericArrayType((GenericArrayType) type, srcType, declaringClass);
} else {
return type;//Class 类型
}
}
private void cacheRefElement(XNode context) {
if (context != null) {
//将当前Mapper 配置文件的namespace 与被引用的Cache 所在的namespace 之间的对应关系,记录到Configuration.cacheRefMap 集合中
configuration.addCacheRef(builderAssistant.getCurrentNamespace(), context.getStringAttribute("namespace"));
//创建CacheRefResolver 对象
CacheRefResolver cacheRefResolver = new CacheRefResolver(builderAssistant, context.getStringAttribute("namespace"));
try {
//解析Cache 引用,该过程主要是设置MapperBuilderAssistant 中的currentCache 和unresolvedCacheRef 字段
cacheRefResolver.resolveCacheRef();
} catch (IncompleteElementException e) {
//如解析过程出现异常,则添加到Configuration.incompleteCacheRefs 集合, 稍后再解析
configuration.addIncompleteCacheRef(cacheRefResolver);
}
}
}
public Cache resolveCacheRef() {
return assistant.useCacheRef(cacheRefNamespace);
}
public Cache useCacheRef(String namespace) {
if (namespace == null) {
throw new BuilderException("cache-ref element requires a namespace attribute.");
}
try {
// 标识未成功解析Cache 引用
unresolvedCacheRef = true;
// 获取namespace对应的Cache 对象
Cache cache = configuration.getCache(namespace);
if (cache == null) {
throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.");
}
// 记录当前命名空间使用的Cache
currentCache = cache;
// 标识已成功解析Cache 引用
unresolvedCacheRef = false;
return cache;
} catch (IllegalArgumentException e) {
throw new IncompleteElementException("No cache for namespace '" + namespace + "' could be found.", e);
}
}
private void cacheElement(XNode context) {
if (context != null) {
//获取< cache >节点的type ),默认位是PERPETUAL
String type = context.getStringAttribute("type", "PERPETUAL");
Class<? extends Cache> typeClass = typeAliasRegistry.resolveAlias(type);
//获取< cache > 节点的eviction 属性,默认LRU
String eviction = context.getStringAttribute("eviction", "LRU");
//解析eviction 属性指定的Cache 装饰器类型
Class<? extends Cache> evictionClass = typeAliasRegistry.resolveAlias(eviction);
Long flushInterval = context.getLongAttribute("flushInterval");
Integer size = context.getIntAttribute("size");
boolean readWrite = !context.getBooleanAttribute("readOnly", false);
boolean blocking = context.getBooleanAttribute("blocking", false);
//获取< cache >节点下的子节点,将用于初始化二级缓存
Properties props = context.getChildrenAsProperties();
//通过MapperBuilderAssistant 创建Cache 对象,并添加到Configuration . caches 集合中保存
builderAssistant.useNewCache(typeClass, evictionClass, flushInterval, size, readWrite, blocking, props);
}
}
public Cache useNewCache(Class<? extends Cache> typeClass,
Class<? extends Cache> evictionClass,
Long flushInterval,
Integer size,
boolean readWrite,
boolean blocking,
Properties props) {
Cache cache = new CacheBuilder(currentNamespace)
.implementation(valueOrDefault(typeClass, PerpetualCache.class))
.addDecorator(valueOrDefault(evictionClass, LruCache.class))
.clearInterval(flushInterval)
.size(size)
.readWrite(readWrite)
.blocking(blocking)
.properties(props)
.build();
//将Cache 对象添加到Configuration.caches 集合中保存,其中会将Cache 的id 作为key,Cache 对象本身作为value
configuration.addCache(cache);
//记录当前命名空间使用的cache 对象
currentCache = cache;
return cache;
}
public Cache build() {
/*默认implementation:PerpetualCache
装饰器集合默认:LruCache*/
setDefaultImplementations();
//根据implementation 指定的类型, 通过反射获取参数为String 类型的构造方法,并通过该构造方法创建Cache 对象
Cache cache = newBaseCacheInstance(implementation, id);
//初始化Cache 对象
setCacheProperties(cache);
// issue #352, do not apply decorators to custom caches
//检测cache 对象的类型,如果是PerpetualCache 类型,为其添加decorators 集合中的装饰器;
// 如果是自定义类型的Cache 接口实现,则不添加decorators 集合中的装饰~
if (PerpetualCache.class.equals(cache.getClass())) {
for (Class<? extends Cache> decorator : decorators) {
//通过反射获取参数为Cache 类型的构造方法,并通过该构造方法创建装饰器
cache = newCacheDecoratorInstance(decorator, cache);
// 配置cache对象的属性
setCacheProperties(cache);
}
//添加MyBatis中提供的标准装饰器
cache = setStandardDecorators(cache);
} else if (!LoggingCache.class.isAssignableFrom(cache.getClass())) {
//如果不是LoggingCache 的子类,则添加LoggingCache 装饰器
cache = new LoggingCache(cache);
}
return cache;
}
private void setCacheProperties(Cache cache) {
if (properties != null) {
// cache 对应的创建MetaObject 对象
MetaObject metaCache = SystemMetaObject.forObject(cache);
for (Map.Entry<Object, Object> entry : properties.entrySet()) {
// 配置项的名称, Cache 对应的属性名称
String name = (String) entry.getKey();
// 配置项的值,Cache对应的属性佳
String value = (String) entry.getValue();
//检测cache 是否有该属性对应的setter 方法
if (metaCache.hasSetter(name)) {
//获取该属性的类型
Class<?> type = metaCache.getSetterType(name);
//进行类型转换,并设置该属性值
if (String.class == type) {
metaCache.setValue(name, value);
} else if (int.class == type
|| Integer.class == type) {
metaCache.setValue(name, Integer.valueOf(value));
} else if (long.class == type
|| Long.class == type) {
metaCache.setValue(name, Long.valueOf(value));
} else if (short.class == type
|| Short.class == type) {
metaCache.setValue(name, Short.valueOf(value));
} else if (byte.class == type
|| Byte.class == type) {
metaCache.setValue(name, Byte.valueOf(value));
} else if (float.class == type
|| Float.class == type) {
metaCache.setValue(name, Float.valueOf(value));
} else if (boolean.class == type
|| Boolean.class == type) {
metaCache.setValue(name, Boolean.valueOf(value));
} else if (double.class == type
|| Double.class == type) {
metaCache.setValue(name, Double.valueOf(value));
} else {
throw new CacheException("Unsupported property type for cache: '" + name + "' of type " + type);
}
}
}
}
//如果Cache类继承了InitializingObject 接口, 则调用其initialize () 方法继续自定义的初始化操作
if (InitializingObject.class.isAssignableFrom(cache.getClass())) {
try {
((InitializingObject) cache).initialize();
} catch (Exception e) {
throw new CacheException("Failed cache initialization for '"
+ cache.getId() + "' on '" + cache.getClass().getName() + "'", e);
}
}
}
private Cache setStandardDecorators(Cache cache) {
try {
//创建cache 对象对应的MetaObject 对象
MetaObject metaCache = SystemMetaObject.forObject(cache);
if (size != null && metaCache.hasSetter("size")) {
metaCache.setValue("size", size);
}
//检测是否指定了clearinterval 字段
if (clearInterval != null) {
//添加ScheduledCache 装饰器
cache = new ScheduledCache(cache);
// 设置ScheduledCache 的clearInterval 字段
((ScheduledCache) cache).setClearInterval(clearInterval);
}
//是否只读,对应添加SerializedCache装饰器
if (readWrite) {
cache = new SerializedCache(cache);
}
//默认添加LoggingCache 和SynchronizedCache 两个装饰器
cache = new LoggingCache(cache);
cache = new SynchronizedCache(cache);
//是否阻塞,对应添加BlockingCache 装饰器
if (blocking) {
cache = new BlockingCache(cache);
}
return cache;
} catch (Exception e) {
throw new CacheException("Error building standard cache decorators. Cause: " + e, e);
}
}
private void buildStatementFromContext(List<XNode> list) {
if (configuration.getDatabaseId() != null) {
buildStatementFromContext(list, configuration.getDatabaseId());
}
buildStatementFromContext(list, null);
}
/**
* 解析SQL 节点的入口函数
*/
public void parseStatementNode() {
//获取SQL节点的id以及databaseId属性,若其databaseid属性值与当前使用的数据库不匹 配,则不加载该SQL 节点;
//若存在相同id 且databaseid 不为空的SQL 节点,则不再加载该SQL 节点
String id = context.getStringAttribute("id");
String databaseId = context.getStringAttribute("databaseId");
if (!databaseIdMatchesCurrent(id, databaseId, this.requiredDatabaseId)) {
return;
}
// 根据SQL 节点的名称决定其SqlCommandType
String nodeName = context.getNode().getNodeName();
SqlCommandType sqlCommandType = SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));
boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
boolean flushCache = context.getBooleanAttribute("flushCache", !isSelect);
boolean useCache = context.getBooleanAttribute("useCache", isSelect);
boolean resultOrdered = context.getBooleanAttribute("resultOrdered", false);
// Include Fragments before parsing
//在解析SQL 语句之前,先处理其中的< inclu de > 节点
XMLIncludeTransformer includeParser = new XMLIncludeTransformer(configuration, builderAssistant);
includeParser.applyIncludes(context.getNode());
String parameterType = context.getStringAttribute("parameterType");
Class<?> parameterTypeClass = resolveClass(parameterType);
String lang = context.getStringAttribute("lang");
LanguageDriver langDriver = getLanguageDriver(lang);
// Parse selectKey after includes and remove them.
//解析SQL 节点中的< selectKey>子节 点
processSelectKeyNodes(id, parameterTypeClass, langDriver);
// Parse the SQL (pre: and were parsed and removed)
//完成SQL 节点的解析
KeyGenerator keyGenerator;
//获取< selectKey> 节点对应的SelectKeyGenerator的i d
String keyStatementId = id + SelectKeyGenerator.SELECT_KEY_SUFFIX;
keyStatementId = builderAssistant.applyCurrentNamespace(keyStatementId, true);
// SQL 节点下存在< selectKey >节点
if (configuration.hasKeyGenerator(keyStatementId)) {
keyGenerator = configuration.getKeyGenerator(keyStatementId);
} else {
//根据SQL 节点的useGeneratedKeys 属性值、mybatis-config.xml 中全局的useGeneratedKeys
//配置,以及是否为insert 语句, 决定使用的KeyGenerator 接口实现
keyGenerator = context.getBooleanAttribute("useGeneratedKeys",
configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType))
? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
}
SqlSource sqlSource = langDriver.createSqlSource(configuration, context, parameterTypeClass);
StatementType statementType = StatementType.valueOf(context.getStringAttribute("statementType", StatementType.PREPARED.toString()));
Integer fetchSize = context.getIntAttribute("fetchSize");
Integer timeout = context.getIntAttribute("timeout");
String parameterMap = context.getStringAttribute("parameterMap");
String resultType = context.getStringAttribute("resultType");
Class<?> resultTypeClass = resolveClass(resultType);
String resultMap = context.getStringAttribute("resultMap");
String resultSetType = context.getStringAttribute("resultSetType");
ResultSetType resultSetTypeEnum = resolveResultSetType(resultSetType);
if (resultSetTypeEnum == null) {
resultSetTypeEnum = configuration.getDefaultResultSetType();
}
String keyProperty = context.getStringAttribute("keyProperty");
String keyColumn = context.getStringAttribute("keyColumn");
String resultSets = context.getStringAttribute("resultSets");
//这里会检测SQL 节点中是否配置了< selectKey > 节点、SQL 节点的useGeneratedKeys 属性值、
// mybatis-config.xml 中全局的useGeneratedKeys 配置,以及是否为insert 语句,决定使用的
// KeyGenerator 接口实现。
//通过MapperBuilderAssistant创建MappedStatement 对象,并添加到
// Configuration. mappedStatements 集合中保存
builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
resultSetTypeEnum, flushCache, useCache, resultOrdered,
keyGenerator, keyProperty, keyColumn, databaseId, langDriver, resultSets);
}
public void applyIncludes(Node source) {
//获取mybatis-config.xml 中< properties > 节点下定义的变量集合
Properties variablesContext = new Properties();
Properties configurationVariables = configuration.getVariables();
Optional.ofNullable(configurationVariables).ifPresent(variablesContext::putAll);
// 处理<include>子节点
applyIncludes(source, variablesContext, false);
}
private void applyIncludes(Node source, final Properties variablesContext, boolean included) {
//处理< include >子节点
if (source.getNodeName().equals("include")) {
//查找refid属性指向的<sql>节点,返回的是其深克隆的Node对象
Node toInclude = findSqlFragment(getStringAttribute(source, "refid"), variablesContext);
//解析<include> 节点下的<property> 节点,将得到的键值对添加到variablesContext 中,并
//形成新的Properties 对象返回,用于替换占位符
Properties toIncludeContext = getVariablesContext(source, variablesContext);
//递归处理<include>节点, 在<sql > 节点中可能会使用< include > 引用了其他SQL 片段
applyIncludes(toInclude, toIncludeContext, true);
if (toInclude.getOwnerDocument() != source.getOwnerDocument()) {
toInclude = source.getOwnerDocument().importNode(toInclude, true);
}
//将< include >节点替换成< sql >节点
source.getParentNode().replaceChild(toInclude, source);
// 将< sql > 节点的子节点添加到< sql >节点前面
while (toInclude.hasChildNodes()) {
toInclude.getParentNode().insertBefore(toInclude.getFirstChild(), toInclude);
}
// 删除<sql> 节点
toInclude.getParentNode().removeChild(toInclude);
} else if (source.getNodeType() == Node.ELEMENT_NODE) {
//处理SQL节点子节点
if (included && !variablesContext.isEmpty()) {
// replace variables in attribute values
NamedNodeMap attributes = source.getAttributes();
//遍历当前SQL 语句的子节点
for (int i = 0; i < attributes.getLength(); i++) {
Node attr = attributes.item(i);
attr.setNodeValue(PropertyParser.parse(attr.getNodeValue(), variablesContext));
}
}
NodeList children = source.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
applyIncludes(children.item(i), variablesContext, included);
}
} else if (included && (source.getNodeType() == Node.TEXT_NODE || source.getNodeType() == Node.CDATA_SECTION_NODE)
&& !variablesContext.isEmpty()) {
// replace variables in text node
//使用之前解析得到的Properties 对象替换对应的占位符
source.setNodeValue(PropertyParser.parse(source.getNodeValue(), variablesContext));
}
}
private Node findSqlFragment(String refid, Properties variables) {
refid = PropertyParser.parse(refid, variables);
//refid=命名空间.refid
refid = builderAssistant.applyCurrentNamespace(refid, true);
try {
//根据refid获取节点
XNode nodeToInclude = configuration.getSqlFragments().get(refid);
return nodeToInclude.getNode().cloneNode(true);
} catch (IllegalArgumentException e) {
throw new IncompleteElementException("Could not find SQL statement to include with refid '" + refid + "'", e);
}
}
private Properties getVariablesContext(Node node, Properties inheritedVariablesContext) {
Map<String, String> declaredProperties = null;
NodeList children = node.getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
Node n = children.item(i);
if (n.getNodeType() == Node.ELEMENT_NODE) {
String name = getStringAttribute(n, "name");
// Replace variables inside
String value = PropertyParser.parse(getStringAttribute(n, "value"), inheritedVariablesContext);
if (declaredProperties == null) {
declaredProperties = new HashMap<>();
}
if (declaredProperties.put(name, value) != null) {
throw new BuilderException("Variable " + name + " defined twice in the same include definition");
}
}
}
if (declaredProperties == null) {
return inheritedVariablesContext;
} else {
Properties newProperties = new Properties();
newProperties.putAll(inheritedVariablesContext);
newProperties.putAll(declaredProperties);
return newProperties;
}
}
private void processSelectKeyNodes(String id, Class<?> parameterTypeClass, LanguageDriver langDriver) {
//获取全部的< selectKey> 节点
List<XNode> selectKeyNodes = context.evalNodes("selectKey");
//解析< selectKey >节点
if (configuration.getDatabaseId() != null) {
parseSelectKeyNodes(id, selectKeyNodes, parameterTypeClass, langDriver, configuration.getDatabaseId());
}
parseSelectKeyNodes(id, selectKeyNodes, parameterTypeClass, langDriver, null);
//移除< selectKey >节点
removeSelectKeyNodes(selectKeyNodes);
}
private void parseSelectKeyNodes(String parentId, List<XNode> list, Class<?> parameterTypeClass, LanguageDriver langDriver, String skRequiredDatabaseId) {
for (XNode nodeToHandle : list) {
String id = parentId + SelectKeyGenerator.SELECT_KEY_SUFFIX;
String databaseId = nodeToHandle.getStringAttribute("databaseId");
if (databaseIdMatchesCurrent(id, databaseId, skRequiredDatabaseId)) {
parseSelectKeyNode(id, nodeToHandle, parameterTypeClass, langDriver, databaseId);
}
}
}
private void parseSelectKeyNode(String id, XNode nodeToHandle, Class<?> parameterTypeClass, LanguageDriver langDriver, String databaseId) {
//获取< selectKey >节点的result Type 、statement Type 、keyProperty 等属性
String resultType = nodeToHandle.getStringAttribute("resultType");
Class<?> resultTypeClass = resolveClass(resultType);
StatementType statementType = StatementType.valueOf(nodeToHandle.getStringAttribute("statementType", StatementType.PREPARED.toString()));
String keyProperty = nodeToHandle.getStringAttribute("keyProperty");
String keyColumn = nodeToHandle.getStringAttribute("keyColumn");
boolean executeBefore = "BEFORE".equals(nodeToHandle.getStringAttribute("order", "AFTER"));
// 设置一系列MappedStatement 对象需要的默认配置,例如, useCache 、fetchSize 等
// defaults
boolean useCache = false;
boolean resultOrdered = false;
KeyGenerator keyGenerator = NoKeyGenerator.INSTANCE;
Integer fetchSize = null;
Integer timeout = null;
boolean flushCache = false;
String parameterMap = null;
String resultMap = null;
ResultSetType resultSetTypeEnum = null;
//通过LanguageDriver.createSqlSource ()方法生成SqlSource
SqlSource sqlSource = langDriver.createSqlSource(configuration, nodeToHandle, parameterTypeClass);
//
SqlCommandType sqlCommandType = SqlCommandType.SELECT;
//通过MapperBuilderAssistant 创建MappedStatement 对象,并添加到
// Configuration.mappedStatements 集合中保存,该集合为StrictMap
builderAssistant.addMappedStatement(id, sqlSource, statementType, sqlCommandType,
fetchSize, timeout, parameterMap, parameterTypeClass, resultMap, resultTypeClass,
resultSetTypeEnum, flushCache, useCache, resultOrdered,
keyGenerator, keyProperty, keyColumn, databaseId, langDriver, null);
id = builderAssistant.applyCurrentNamespace(id, false);
MappedStatement keyStatement = configuration.getMappedStatement(id, false);
//创建< selectKey > 节点对应的KeyGenerator ,添加到Configuration . keyGenerators 集合中
//保存, Configuration.keyGenerators 字段是StrictMap
configuration.addKeyGenerator(id, new SelectKeyGenerator(keyStatement, executeBefore));
}
@Override
public SqlSource createSqlSource(Configuration configuration, XNode script, Class<?> parameterType) {
XMLScriptBuilder builder = new XMLScriptBuilder(configuration, script, parameterType);
return builder.parseScriptNode();
}
public SqlSource parseScriptNode() {
//首先判断当前的节点是不是有动态SQL ,动态SQL 会包括占位符或是动态SQL 的相关节点
MixedSqlNode rootSqlNode = parseDynamicTags(context);
SqlSource sqlSource;
//根据是否是动态SQL , 创建相应的SqlSource 对象
if (isDynamic) {
sqlSource = new DynamicSqlSource(configuration, rootSqlNode);
} else {
sqlSource = new RawSqlSource(configuration, rootSqlNode, parameterType);
}
return sqlSource;
}
protected MixedSqlNode parseDynamicTags(XNode node) {
//用于记录生成的SqlNode 集合
List<SqlNode> contents = new ArrayList<>();
//获取SelectKey 的所有子节点
NodeList children = node.getNode().getChildNodes();
for (int i = 0; i < children.getLength(); i++) {
//创建XNode ,该过程会将能解析掉的” ${} ” 都解析掉
XNode child = node.newXNode(children.item(i));
if (child.getNode().getNodeType() == Node.CDATA_SECTION_NODE || child.getNode().getNodeType() == Node.TEXT_NODE) {
String data = child.getStringBody("");
TextSqlNode textSqlNode = new TextSqlNode(data);
//解析SQL 语句,如果含有未解析的”${}”占位符,则为动态SQL
if (textSqlNode.isDynamic()) {
contents.add(textSqlNode);
// 标记为动态SQL 语句
isDynamic = true;
} else {
contents.add(new StaticTextSqlNode(data));
}
} else if (child.getNode().getNodeType() == Node.ELEMENT_NODE) { // issue #628
//如果子节点是一个标签,那么一定是动态SQL ,并且根据不同的动态标签生成不同的NodeHandler
String nodeName = child.getNode().getNodeName();
//根据标签名称获取对应 的NodeHandler 对象
//处理where之类
NodeHandler handler = nodeHandlerMap.get(nodeName);
if (handler == null) {
throw new BuilderException("Unknown element <" + nodeName + "> in SQL statement.");
}
//处理动态SQL ,并将解析得到的SqlNode 对象放入contents 集合中保存
handler.handleNode(child, contents);
isDynamic = true;
}
}
// SqlNode 集合包装成一个MixedSqlNode
return new MixedSqlNode(contents);
}
/**
* 当解析到${}则设置动态
* @return
*/
public boolean isDynamic() {
DynamicCheckerTokenParser checker = new DynamicCheckerTokenParser();
GenericTokenParser parser = createParser(checker);
parser.parse(text);
return checker.isDynamic();
}
public RawSqlSource(Configuration configuration, SqlNode rootSqlNode, Class<?> parameterType) {
//调用getSql ()方法,完成SQL 语句的拼接和初步解析
this(configuration, getSql(configuration, rootSqlNode), parameterType);
}
private static String getSql(Configuration configuration, SqlNode rootSqlNode) {
DynamicContext context = new DynamicContext(configuration, null);
rootSqlNode.apply(context);
return context.getSql();
}
public DynamicContext(Configuration configuration, Object parameterObject) {
if (parameterObject != null && !(parameterObject instanceof Map)) {
//对于非Map 类型的参数,会创建对应的MetaObject 对象,并封装成ContextMap 对象
MetaObject metaObject = configuration.newMetaObject(parameterObject);
boolean existsTypeHandler = configuration.getTypeHandlerRegistry().hasTypeHandler(parameterObject.getClass());
bindings = new ContextMap(metaObject, existsTypeHandler);
} else {
bindings = new ContextMap(null, false);
}
bindings.put(PARAMETER_OBJECT_KEY, parameterObject);
bindings.put(DATABASE_ID_KEY, configuration.getDatabaseId());
}
public RawSqlSource(Configuration configuration, String sql, Class<?> parameterType) {
//通过SqlSourceBuilder 完成占住符的解析和替换操作
SqlSourceBuilder sqlSourceParser = new SqlSourceBuilder(configuration);
Class<?> clazz = parameterType == null ? Object.class : parameterType;
sqlSource = sqlSourceParser.parse(sql, clazz, new HashMap<>());
}
public ParameterMappingTokenHandler(Configuration configuration, Class<?> parameterType, Map<String, Object> additionalParameters) {
super(configuration);
this.parameterType = parameterType;
this.metaParameters = configuration.newMetaObject(additionalParameters);
}
public MetaObject newMetaObject(Object object) {
return MetaObject.forObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
public static MetaObject forObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
if (object == null) {
// 若object 为null ,则统一返回SystemMetaObject.NULL_META_OBJECT 这个标志对象
return SystemMetaObject.NULL_META_OBJECT;
} else {
return new MetaObject(object, objectFactory, objectWrapperFactory, reflectorFactory);
}
}
private MetaObject(Object object, ObjectFactory objectFactory, ObjectWrapperFactory objectWrapperFactory, ReflectorFactory reflectorFactory) {
this.originalObject = object;
this.objectFactory = objectFactory;
this.objectWrapperFactory = objectWrapperFactory;
this.reflectorFactory = reflectorFactory;
if (object instanceof ObjectWrapper) {
this.objectWrapper = (ObjectWrapper) object;
} else if (objectWrapperFactory.hasWrapperFor(object)) {
//若ObjectWrapperFactory 能够为该原始对象创建对应的ObjectWrapper 对象,则由优先使用ObjectWrapperFactory
//而DefaultObjectWrapperFactory.hasWrapperFor ()始终
//返回false 。用户可以自定义ObjectWrapperFactory 实现进行扩展
this.objectWrapper = objectWrapperFactory.getWrapperFor(this, object);
} else if (object instanceof Map) {
this.objectWrapper = new MapWrapper(this, (Map) object);
} else if (object instanceof Collection) {
this.objectWrapper = new CollectionWrapper(this, (Collection) object);
} else {
this.objectWrapper = new BeanWrapper(this, object);
}
}
public MappedStatement addMappedStatement(
String id,
SqlSource sqlSource,
StatementType statementType,
SqlCommandType sqlCommandType,
Integer fetchSize,
Integer timeout,
String parameterMap,
Class<?> parameterType,
String resultMap,
Class<?> resultType,
ResultSetType resultSetType,
boolean flushCache,
boolean useCache,
boolean resultOrdered,
KeyGenerator keyGenerator,
String keyProperty,
String keyColumn,
String databaseId,
LanguageDriver lang,
String resultSets) {
if (unresolvedCacheRef) {
throw new IncompleteElementException("Cache-ref not yet resolved");
}
id = applyCurrentNamespace(id, false);
boolean isSelect = sqlCommandType == SqlCommandType.SELECT;
MappedStatement.Builder statementBuilder = new MappedStatement.Builder(configuration, id, sqlSource, sqlCommandType)
.resource(resource)
.fetchSize(fetchSize)
.timeout(timeout)
.statementType(statementType)
.keyGenerator(keyGenerator)
.keyProperty(keyProperty)
.keyColumn(keyColumn)
.databaseId(databaseId)
.lang(lang)
.resultOrdered(resultOrdered)
.resultSets(resultSets)
.resultMaps(getStatementResultMaps(resultMap, resultType, id))
.resultSetType(resultSetType)
.flushCacheRequired(valueOrDefault(flushCache, !isSelect))
.useCache(valueOrDefault(useCache, isSelect))
.cache(currentCache);
ParameterMap statementParameterMap = getStatementParameterMap(parameterMap, parameterType, id);
if (statementParameterMap != null) {
statementBuilder.parameterMap(statementParameterMap);
}
MappedStatement statement = statementBuilder.build();
configuration.addMappedStatement(statement);
return statement;
}
private ParameterMap getStatementParameterMap(
String parameterMapName,
Class<?> parameterTypeClass,
String statementId) {
parameterMapName = applyCurrentNamespace(parameterMapName, true);
ParameterMap parameterMap = null;
if (parameterMapName != null) {
try {
parameterMap = configuration.getParameterMap(parameterMapName);
} catch (IllegalArgumentException e) {
throw new IncompleteElementException("Could not find parameter map " + parameterMapName, e);
}
} else if (parameterTypeClass != null) {
List<ParameterMapping> parameterMappings = new ArrayList<>();
parameterMap = new ParameterMap.Builder(
configuration,
statementId + "-Inline",
parameterTypeClass,
parameterMappings).build();
}
return parameterMap;
}
public Builder(Configuration configuration, String id, SqlSource sqlSource, SqlCommandType sqlCommandType) {
mappedStatement.configuration = configuration;
mappedStatement.id = id;
mappedStatement.sqlSource = sqlSource;
mappedStatement.statementType = StatementType.PREPARED;
mappedStatement.resultSetType = ResultSetType.DEFAULT;
mappedStatement.parameterMap = new ParameterMap.Builder(configuration, "defaultParameterMap", null, new ArrayList<>()).build();
mappedStatement.resultMaps = new ArrayList<>();
mappedStatement.sqlCommandType = sqlCommandType;
//设置主键生成策略
mappedStatement.keyGenerator = configuration.isUseGeneratedKeys() && SqlCommandType.INSERT.equals(sqlCommandType) ? Jdbc3KeyGenerator.INSTANCE : NoKeyGenerator.INSTANCE;
String logId = id;
if (configuration.getLogPrefix() != null) {
logId = configuration.getLogPrefix() + id;
}
mappedStatement.statementLog = LogFactory.getLog(logId);
mappedStatement.lang = configuration.getDefaultScriptingLanguageInstance();
}