中文文档:https://mybatis.org/mybatis-3/zh/getting-started.html
mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<properties resource="config.properties">
<!-- 按需定义全局变量,以供整个配置文件使用-->
<!-- <property name="globalVariable" value="value"/>-->
</properties>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${mysql.driver}"/>
<property name="url" value="${mysql.url}"/>
<property name="username" value="${mysql.username}"/>
<property name="password" value="${mysql.password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="mapper/PersonMapper.xml"/>
</mappers>
</configuration>
测试入口:
package com.laoxu.mybatis.executor;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import java.io.IOException;
import java.io.InputStream;
public class start {
public static void main(String[] args) throws IOException {
// user.dir指定了当前的路径
String userDir = System.getProperty("user.dir");
System.out.println(userDir);
// 获取类路径
String classPath = start.class.getResource("/").getPath();
System.out.println(classPath);
// 根据当前类路径下的相对路径 (classPath + {path})
String resource = "mapper/mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
}
构建SqlSessionFactory工厂:入参(输入流)
/**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.session;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
import org.apache.ibatis.builder.xml.XMLConfigBuilder;
import org.apache.ibatis.exceptions.ExceptionFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.session.defaults.DefaultSqlSessionFactory;
/**
* Builds {@link SqlSession} instances.
*
* @author Clinton Begin
*/
public class SqlSessionFactoryBuilder {
// 构造1
public SqlSessionFactory build(InputStream inputStream) {
return build(inputStream, null, null);
}
// 构造2
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
return build(parser.parse());
} catch (Exception e) {
throw ExceptionFactory.wrapException("Error building SqlSession.", e);
} finally {
ErrorContext.instance().reset();
try {
inputStream.close();
} catch (IOException e) {
// Intentionally ignore. Prefer previous error.
}
}
}
// 构造3
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
}
SqlSessionFactoryBuilder 构造2:
构造xml配置
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
/**
* Copyright 2009-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.builder.xml;
import java.io.InputStream;
import java.io.Reader;
import java.util.Properties;
import javax.sql.DataSource;
import org.apache.ibatis.builder.BaseBuilder;
import org.apache.ibatis.builder.BuilderException;
import org.apache.ibatis.datasource.DataSourceFactory;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.loader.ProxyFactory;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.io.VFS;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.mapping.DatabaseIdProvider;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.parsing.XNode;
import org.apache.ibatis.parsing.XPathParser;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaClass;
import org.apache.ibatis.reflection.ReflectorFactory;
import org.apache.ibatis.reflection.factory.ObjectFactory;
import org.apache.ibatis.reflection.wrapper.ObjectWrapperFactory;
import org.apache.ibatis.session.AutoMappingBehavior;
import org.apache.ibatis.session.AutoMappingUnknownColumnBehavior;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.LocalCacheScope;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.type.JdbcType;
/**
* @author Clinton Begin
* @author Kazuki Shimizu
*/
public class XMLConfigBuilder extends BaseBuilder {
private boolean parsed;
private final XPathParser parser;
private String environment;
// 构造1
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()), environment, props);
}
// 构造2
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration());
ErrorContext.instance().resource("SQL Mapper Configuration");
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
}
- XMLConfigBuilder 需要构造的实体类:
new XMLMapperEntityResolver()
new XPathParser(inputStream, true, props, new XMLMapperEntityResolver())
new Configuration()
解析开始:
1、实例化一个XML映射实体解析器
/**
* Copyright 2009-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.builder.xml;
import java.io.IOException;
import java.io.InputStream;
import java.util.Locale;
import org.apache.ibatis.io.Resources;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
/**
* MyBatis dtd的离线实体解析器。
*
* @author Clinton Begin
* @author Eduardo Macarron
*/
public class XMLMapperEntityResolver implements EntityResolver {
private static final String IBATIS_CONFIG_SYSTEM = "ibatis-3-config.dtd";
private static final String IBATIS_MAPPER_SYSTEM = "ibatis-3-mapper.dtd";
private static final String MYBATIS_CONFIG_SYSTEM = "mybatis-3-config.dtd";
private static final String MYBATIS_MAPPER_SYSTEM = "mybatis-3-mapper.dtd";
private static final String MYBATIS_CONFIG_DTD = "org/apache/ibatis/builder/xml/mybatis-3-config.dtd";
private static final String MYBATIS_MAPPER_DTD = "org/apache/ibatis/builder/xml/mybatis-3-mapper.dtd";
/**
* 将公共DTD转换为本地DTD。
*
* @param publicId
* 公共id,在" public "后面
* @param systemId
* 在公共id之后的系统id。
* @return DTD的InputSource
*
* @throws org.xml.sax.SAXException
* 如果出了什么差错
*/
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException {
// 去读取mybatis-config.xml头标签<!DOCTYPE configuration ...param>的两个参数
try {
if (systemId != null) {
// 系统id小写处理
String lowerCaseSystemId = systemId.toLowerCase(Locale.ENGLISH);
if (lowerCaseSystemId.contains(MYBATIS_CONFIG_SYSTEM) ||
lowerCaseSystemId.contains(IBATIS_CONFIG_SYSTEM)) {
// 如果系统id包含 系统配置 标识
return getInputSource(MYBATIS_CONFIG_DTD, publicId, systemId);
} else if (lowerCaseSystemId.contains(MYBATIS_MAPPER_SYSTEM) ||
lowerCaseSystemId.contains(IBATIS_MAPPER_SYSTEM)) {
// 如果系统id包含 映射系统 标识
return getInputSource(MYBATIS_MAPPER_DTD, publicId, systemId);
}
}
return null;
} catch (Exception e) {
throw new SAXException(e.toString());
}
}
/**
* 获取输入源
* @param path 路径
* @param publicId 公共id
* @param systemId 系统Id
* @return
*/
private InputSource getInputSource(String path, String publicId, String systemId) {
InputSource source = null;
if (path != null) {
try {
// 去类路径获取输入流
InputStream in = Resources.getResourceAsStream(path);
source = new InputSource(in);
source.setPublicId(publicId);
source.setSystemId(systemId);
} catch (IOException e) {
// 忽略,null也可以
}
}
return source;
}
}
2、实例化XPathParser解析器
/**
* Copyright 2009-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.parsing;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import javax.xml.XMLConstants;
import javax.xml.namespace.QName;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import org.apache.ibatis.builder.BuilderException;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
/**
* @author Clinton Begin
* @author Kazuki Shimizu
*/
public class XPathParser {
private final Document document;
private boolean validation;
private EntityResolver entityResolver;
private Properties variables;
private XPath xpath;
public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
commonConstructor(validation, variables, entityResolver);
this.document = createDocument(new InputSource(inputStream));
}
private Document createDocument(InputSource inputSource) {
// 重要提示:这个函数只能在通用构造函数之后调用
try {
//创建DocumentBuilderFactory实例对象
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
/**
* 设置是否启用DTD验证
*/
factory.setValidating(validation);
/**
* 设置是否支持XML名称空间
*/
factory.setNamespaceAware(false);
/**
* 设置解析器是否忽略注释
*/
factory.setIgnoringComments(true);
/**
* 设置必须删除元素内容中的空格(有时也可以称作“可忽略空格”,请参阅 XML Rec 2.10)。
* 注意,只有在空格直接包含在元素内容中,并且该元素内容是只有一个元素的内容模式时,
* 才能删除空格(请参阅 XML Rec 3.2.1)。由于依赖于内容模式,因此此设置要求解析器处于验证模式。默认情况下,其值设置为 false。
*/
factory.setIgnoringElementContentWhitespace(false);
/**
* 指定由此代码生成的解析器将把 CDATA 节点转换为 Text 节点,并将其附加到相邻(如果有)的 Text 节点。默认情况下,其值设置为 false。
*/
factory.setCoalescing(false);
/**
* 指定由此代码生成的解析器将扩展实体引用节点。默认情况下,此值设置为 true。
*/
factory.setExpandEntityReferences(true);
//创建DocumentBuilder实例对象
DocumentBuilder builder = factory.newDocumentBuilder();
//指定使用 EntityResolver 解析要解析的 XML 文档中存在的实体。将其设置为 null 将会导致底层实现使用其自身的默认实现和行为。
builder.setEntityResolver(entityResolver);
//指定解析器要使用的 ErrorHandler。将其设置为 null 将会导致底层实现使用其自身的默认实现和行为。
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
}
});
return builder.parse(inputSource);
} catch (Exception e) {
throw new BuilderException("Error creating document instance. Cause: " + e, e);
}
}
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();
}
}
3、实例化Configuration核心配置类
主要作用:注册工厂及驱动,并设置别名
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);
languageRegistry.setDefaultDriverClass(XMLLanguageDriver.class);
languageRegistry.register(RawLanguageDriver.class);
}
private final Map<String, Class<?>> typeAliases = new HashMap<>();
对alias进行小写化,将别名作为key,class作为value存入typeAliases这个map中
private final Map<Class<? extends LanguageDriver>, LanguageDriver> LANGUAGE_DRIVER_MAP = new HashMap<>();
public void register(Class<? extends LanguageDriver> cls) {
if (cls == null) {
throw new IllegalArgumentException("null is not a valid Language Driver");
}
MapUtil.computeIfAbsent(LANGUAGE_DRIVER_MAP, cls, k -> {
try {
return k.getDeclaredConstructor().newInstance();
} catch (Exception ex) {
throw new ScriptingException("Failed to load language driver for " + cls.getName(), ex);
}
});
}
MapUtil.computeIfAbsent静态方法
public static <K, V> V computeIfAbsent(Map<K, V> map, K key, Function<K, V> mappingFunction) {
V value = map.get(key);
if (value != null) {
return value;
}
return map.computeIfAbsent(key, mappingFunction::apply);
}
对传入的map进行判断,判断传入的key是否存在于map中,如果存在直接返回;如果不存在,那么就计算后返回------mappingFunction代表我们自定义的函数,如果该函数返回不为空那么就put(key, 函数返回的值),否则不对map进行操作。
4、错误上下文进行赋值
主要作用:对当前线程的 ErrorContext 类的 resource 属性进行赋值
ErrorContext.instance().resource("SQL Mapper Configuration");
/**
* Copyright 2009-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.ibatis.executor;
/**
* @author Clinton Begin
*/
public class ErrorContext {
private static final String LINE_SEPARATOR = System.lineSeparator();
private static final ThreadLocal<ErrorContext> LOCAL = ThreadLocal.withInitial(ErrorContext::new);
private ErrorContext stored;
private String resource;
private String activity;
private String object;
private String message;
private String sql;
private Throwable cause;
private ErrorContext() {
}
public static ErrorContext instance() {
return LOCAL.get();
}
public ErrorContext resource(String resource) {
this.resource = resource;
return this;
}
public ErrorContext reset() {
resource = null;
activity = null;
object = null;
message = null;
sql = null;
cause = null;
LOCAL.remove();
return this;
}
}
5、parser.json
{
"configuration": {
"aggressiveLazyLoading": false,
"autoMappingBehavior": "PARTIAL",
"autoMappingUnknownColumnBehavior": "NONE",
"cacheEnabled": true,
"cacheNames": [],
"caches": [],
"callSettersOnNulls": false,
"defaultExecutorType": "SIMPLE",
"defaultScriptingLanguageInstance": {},
"defaultScriptingLanuageInstance": {},
"incompleteCacheRefs": [],
"incompleteMethods": [],
"incompleteResultMaps": [],
"incompleteStatements": [],
"interceptors": [],
"jdbcTypeForNull": "OTHER",
"keyGeneratorNames": [],
"keyGenerators": [],
"languageRegistry": {
"defaultDriver": {},
"defaultDriverClass": "org.apache.ibatis.scripting.xmltags.XMLLanguageDriver"
},
"lazyLoadTriggerMethods": [
"hashCode",
"equals",
"clone",
"toString"
],
"lazyLoadingEnabled": false,
"localCacheScope": "SESSION",
"mapUnderscoreToCamelCase": false,
"mappedStatementNames": [],
"mappedStatements": [],
"mapperRegistry": {
"mappers": []
},
"multipleResultSetsEnabled": true,
"objectFactory": {},
"objectWrapperFactory": {},
"parameterMapNames": [],
"parameterMaps": [],
"proxyFactory": {},
"reflectorFactory": {
"classCacheEnabled": true
},
"resultMapNames": [],
"resultMaps": [],
"returnInstanceForEmptyRow": false,
"safeResultHandlerEnabled": true,
"safeRowBoundsEnabled": false,
"shrinkWhitespacesInSql": false,
"sqlFragments": {},
"typeAliasRegistry": {
"typeAliases": {
"date": "java.util.Date",
"_boolean": "boolean",
"cglib": "org.apache.ibatis.executor.loader.cglib.CglibProxyFactory",
"_byte[]": "[B",
"_int[]": "[I",
"object[]": "[Ljava.lang.Object;",
"decimal[]": "[Ljava.math.BigDecimal;",
"integer": "java.lang.Integer",
"float": "java.lang.Float",
"perpetual": "org.apache.ibatis.cache.impl.PerpetualCache",
"_byte": "byte",
"iterator": "java.util.Iterator",
"biginteger[]": "[Ljava.math.BigInteger;",
"xml": "org.apache.ibatis.scripting.xmltags.XMLLanguageDriver",
"_double": "double",
"_int": "int",
"hashmap": "java.util.HashMap",
"_float[]": "[F",
"soft": "org.apache.ibatis.cache.decorators.SoftCache",
"javassist": "org.apache.ibatis.executor.loader.javassist.JavassistProxyFactory",
"date[]": "[Ljava.util.Date;",
"bigdecimal[]": "[Ljava.math.BigDecimal;",
"slf4j": "org.apache.ibatis.logging.slf4j.Slf4jImpl",
"byte": "java.lang.Byte",
"double": "java.lang.Double",
"resultset": "java.sql.ResultSet",
"raw": "org.apache.ibatis.scripting.defaults.RawLanguageDriver",
"collection": "java.util.Collection",
"list": "java.util.List",
"lru": "org.apache.ibatis.cache.decorators.LruCache",
"_float": "float",
"_long": "long",
"_integer": "int",
"_integer[]": "[I",
"boolean[]": "[Ljava.lang.Boolean;",
"decimal": "java.math.BigDecimal",
"_double[]": "[D",
"object": "java.lang.Object",
"biginteger": "java.math.BigInteger",
"string": "java.lang.String",
"long[]": "[Ljava.lang.Long;",
"jdbc": "org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory",
"long": "java.lang.Long",
"weak": "org.apache.ibatis.cache.decorators.WeakCache",
"no_logging": "org.apache.ibatis.logging.nologging.NoLoggingImpl",
"unpooled": "org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory",
"pooled": "org.apache.ibatis.datasource.pooled.PooledDataSourceFactory",
"db_vendor": "org.apache.ibatis.mapping.VendorDatabaseIdProvider",
"managed": "org.apache.ibatis.transaction.managed.ManagedTransactionFactory",
"commons_logging": "org.apache.ibatis.logging.commons.JakartaCommonsLoggingImpl",
"_short[]": "[S",
"_short": "short",
"map": "java.util.Map",
"log4j": "org.apache.ibatis.logging.log4j.Log4jImpl",
"jdk_logging": "org.apache.ibatis.logging.jdk14.Jdk14LoggingImpl",
"fifo": "org.apache.ibatis.cache.decorators.FifoCache",
"bigdecimal": "java.math.BigDecimal",
"short[]": "[Ljava.lang.Short;",
"int[]": "[Ljava.lang.Integer;",
"arraylist": "java.util.ArrayList",
"int": "java.lang.Integer",
"float[]": "[Ljava.lang.Float;",
"log4j2": "org.apache.ibatis.logging.log4j2.Log4j2Impl",
"byte[]": "[Ljava.lang.Byte;",
"boolean": "java.lang.Boolean",
"stdout_logging": "org.apache.ibatis.logging.stdout.StdOutImpl",
"double[]": "[Ljava.lang.Double;",
"_long[]": "[J",
"jndi": "org.apache.ibatis.datasource.jndi.JndiDataSourceFactory",
"short": "java.lang.Short",
"_boolean[]": "[Z",
"integer[]": "[Ljava.lang.Integer;"
}
},
"typeHandlerRegistry": {
"typeHandlers": [
{
"rawType": "java.math.BigDecimal"
},
{
"rawType": "[Ljava.lang.Byte;"
},
{
"rawType": "java.lang.String"
},
{
"rawType": "java.util.Date"
},
{
"rawType": "java.time.OffsetTime"
},
{
"rawType": "java.time.Year"
},
{
"rawType": "java.time.chrono.JapaneseDate"
},
{
"rawType": "java.util.Date"
},
{
"rawType": "java.math.BigInteger"
},
{
"rawType": "java.time.LocalDateTime"
},
{
"rawType": "java.time.LocalTime"
},
{
"rawType": "java.lang.String"
},
{
"rawType": "java.lang.Integer"
},
{
"rawType": "java.lang.String"
},
{
"rawType": "java.time.LocalDate"
},
{
"rawType": "java.lang.Character"
},
{
"rawType": "java.lang.Short"
},
{
"rawType": "java.io.Reader"
},
{
"rawType": "java.lang.Boolean"
},
{
"rawType": "java.lang.String"
},
{
"rawType": "java.time.Month"
},
{
"rawType": "java.sql.Time"
},
{
"rawType": "[Ljava.lang.Byte;"
},
{
"rawType": "java.lang.Double"
},
{
"rawType": "java.lang.String"
},
{
"rawType": "java.lang.Object"
},
{
"rawType": "java.sql.Timestamp"
},
{
"rawType": "java.time.YearMonth"
},
{
"rawType": "java.lang.Byte"
},
{
"rawType": "java.time.ZonedDateTime"
},
{
"rawType": "[B"
},
{
"rawType": "[B"
},
{
"rawType": "java.time.Instant"
},
{
"rawType": "java.lang.Float"
},
{
"rawType": "java.sql.Date"
},
{
"rawType": "java.time.OffsetDateTime"
},
{
"rawType": "java.lang.Long"
},
{
"rawType": "java.lang.Object"
},
{
"rawType": "java.util.Date"
},
{
"rawType": "java.io.InputStream"
}
],
"unknownTypeHandler": {
"rawType": "java.lang.Object"
}
},
"useActualParamName": true,
"useColumnLabel": true,
"useGeneratedKeys": false
}
}
6、解析environments标签
6、解析mappers标签