List of articles
- Mybatis Introductory cases
-
- establish maven engineering , Introduce dependency configuration items
- database
- javabean
- jdbc.properties
- mybatis Core profile
- mapper.xml The mapping file
- Mapper.java Interface
- Test class
- Mybatis Load core profile process
-
- 1. entrance
- 2. Create a 【XMLConfigBuilder】 Parser class
- 3.【XPathParser】 The constructor of the parser
- 4.【XMLMapperEntityResolver】 Entity Resolver
- 5. Go back to 【3】 Step by step : structure XPathParser
- 6. Go back to 【2】 Step by step ,81 Row or so :
-
- 6.1. first line `super(new Configuration());`
- 6.2. **Configuration** Class is Mybatis The core configuration class , It’s so important !
- 7. Go back to the first step SqlSessionFactoryBuilder#build
-
- 7.1 see `org.apache.ibatis.session.SqlSessionFactoryBuilder#build(org.apache.ibatis.session.Configuration)` Method
- 7.2 `parser.parse()` Method
- 7.3 And then execute this method XMLConfigBuilder#parseConfiguration
Mybatis Introductory cases
establish maven engineering , Introduce dependency configuration items
pom.xml Introduction in maven rely on :
<dependencies>
<!--MyBatis coordinate -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.5</version>
</dependency>
<!--mysql drive -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.6</version>
</dependency>
<!-- unit testing -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
database
CREATE DATABASE mybatis;
USE mybatis;
CREATE TABLE `t_user` (
`uid` INT(11) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(40) DEFAULT NULL,
`sex` VARCHAR(10) DEFAULT NULL,
`birthday` DATE DEFAULT NULL,
`address` VARCHAR(40) DEFAULT NULL,
`level` VARCHAR(10) DEFAULT NULL,
PRIMARY KEY (`uid`)
) ENGINE=INNODB DEFAULT CHARSET=utf8;
insert into `t_user`(`uid`,`username`,`sex`,`birthday`,`address`,`level`) values (1,'zs',' male ','2018-08-08',' Beijing ','LOW'),(2,'ls',' Woman ','2018-08-30',' wuhan ','MIDDLE'),(3,'ww',' male ','2018-08-08',' Beijing ','LOW');
javabean
User.java class
public class User implements Serializable {
private int uid; // user id
private String username;// User name
private String sex;// Gender
private Date birthday;// Birthday
private String address;// Address
// get、set...
}
jdbc.properties
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mybatis
username=root
password=root
mybatis Core profile
resources Create under directory :mybatis-config.xml, And write the following :
<?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>
<!-- Import external profile -->
<properties resource="jdbc.properties" />
<settings>
<setting name="lazyLoadingEnabled" value="true"/>
<setting name="useActualParamName" value="true"/>
<setting name="logImpl" value="SLF4J"/>
<!-- Self defined VFS -->
<setting name="vfsImpl" value="org.byron4j.vfs.MyVFS"/>
</settings>
<!-- Alias mode 1 : Single -->
<typeAliases>
<typeAlias alias="user2" type="org.byron4j.bean.User"/>
<typeAlias alias="int" type="java.lang.Integer"/>
<!-- Mode two , All classes in this package are named by default , And case insensitive
Such as : org.byron4j.bean.Product Another name will be product、Product、ProDuCt Fine
-->
<package name="org.byron4j.bean"/>
</typeAliases>
<typeHandlers>
<!-- Mode one : Single processor -->
<!--<typeHandler handler="org.byron4j.handler.MyHandler" javaType="org.byron4j.bean.User"/>-->
<typeHandler handler="org.byron4j.handler.MyDateHandler" javaType="long" jdbcType="TIMESTAMP"/>
<!-- Unified automatic search -->
<package name="org.byron4j.handler"/>
</typeHandlers>
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<!--<databaseIdProvider type="DB_VENDOR" />-->
<mappers>
<mapper resource="org/byron4j/mapper/UserMapper.xml"/>
</mappers>
</configuration>
mapper.xml The mapping file
resources Create a directory under directory org/byron4j/mapper
Catalog ( Note that the directory needs to be consistent with the package level of the interface ), Create a new one UserMapper.xml, Write the following :
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--namespace: The name space , Fully qualified name of the interface -->
<mapper namespace="org.byron4j.mapper.UserMapper">
<!--
id attribute : Same as the method name of the interface
resultType attribute : Return type , Write full name , Set writes the generic type of the element
Tagging body :sql sentence
-->
<!-- The alias is used here User01 Case insensitive ; When there is only one parameter, you can write the parameter name as you like here aaa, But in the actual development, it is recommended to keep consistent with the parameter name -->
<select id="findById" resultType="User01">
select * from t_user where uid = #{aaa}
</select>
</mapper>
Mapper.java Interface
package org.byron4j.mapper
Create an interface :UserMapper.java
public interface UserDao {
User findById(Integer id);
}
Test class
Write a test class :
@Test
public void test() throws Exception {
// 1. Read configuration file as stream
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
// 2. Get... From the core configuration file SqlSessionFactory object
SqlSessionFactory build = new SqlSessionFactoryBuilder().build(is);
// 3. obtain SqlSession object ( similar connection)
SqlSession sqlSession = build.openSession();
// 4. Get proxy object
UserDao mapper = sqlSession.getMapper(UserDao.class);
// 5. operation , Release resources
User user = mapper.findById(2);
System.out.println(user);
sqlSession.close();
is.close();
}
This is a simple introduction case , After using it . We can come to learn Mybatis Loading the core configuration file process .
Mybatis Load core profile process
1. entrance
org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream, java.lang.String)
The first parameter of this method is a mybatis The input stream represented by the configuration file ; The second parameter is the environment , Here we default to .
It calls the following methods :
org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream, java.lang.String, java.util.Properties)
.
In our case, only the first parameter has a value , The back are all null.
Let’s start tracking the source code :
public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
// Create a 【XMLConfigBuilder】 Parser class
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.
}
}
}
2. Create a 【XMLConfigBuilder】 Parser class
Continue tracking org.apache.ibatis.builder.xml.XMLConfigBuilder#XMLConfigBuilder( The core configuration xml file , Environmental Science env, Don't specify properties Then for null)
Method :
public XMLConfigBuilder(InputStream inputStream, String environment, Properties props) {
this(new XPathParser(inputStream, true, props, new XMLMapperEntityResolver()),
environment, props);
}
The method body calls the overloaded constructor :org.apache.ibatis.builder.xml.XMLConfigBuilder#XMLConfigBuilder(org.apache.ibatis.parsing.XPathParser, java.lang.String, java.util.Properties)
The first parameter here is a XPathParser Type of parser ( Look at the name. It’s XPath The parser ).
It’s used here XPathParser Constructors , So let’s see .
3.【XPathParser】 The constructor of the parser
Constructors :org.apache.ibatis.parsing.XPathParser#XPathParser(java.io.InputStream, true, java.util.Properties by null, org.xml.sax.EntityResolver)
The fourth parameter is an entity parser :org.apache.ibatis.builder.xml.XMLMapperEntityResolver, Realized org.xml.sax.EntityResolver Interface ;
So we need to check XMLMapperEntityResolver
What kind of thing is this .
4.【XMLMapperEntityResolver】 Entity Resolver
org.apache.ibatis.builder.xml.XMLMapperEntityResolver, Realized org.xml.sax.EntityResolver Interface
; After implementing this interface , Can be used to customize interception resolution XML, Like using mybatis The definition of constraints can be conditional judgment to do some other logic .
Here is a simple example , Just make a statement :
public class MyResolver implements EntityResolver {
public InputSource resolveEntity (String publicId, String systemId)
{
if (systemId.equals("http://www.myhost.com/today")) {
// Includes custom , Then resolve and process by yourself
MyReader reader = new MyReader();
return new InputSource(reader);
} else {
// use the default behaviour
return null;
}
}
}
XMLMapperEntityResolver This parser is to judge systemId(xml The document declaration of ) contain org/apache/ibatis/builder/xml/mybatis-3-config.dtd
Just use mybatis Self defined InputSource(xml File configuration input source ):
private InputSource getInputSource(String path, String publicId, String systemId) {
InputSource source = null;
if (path != null) {
try {
// path yes mybatis-3-config.dtd The path of
InputStream in = Resources.getResourceAsStream(path);
source = new InputSource(in);
source.setPublicId(publicId);
source.setSystemId(systemId);
} catch (IOException e) {
// ignore, null is ok
}
}
return source;
}
So you should be able to understand through XMLMapperEntityResolver Just got one InputSource object (SAX The parser will use this InputSource Object to determine how to read XML Input ).
5. Go back to 【3】 Step by step : structure XPathParser
XMLMapperEntityResolver After understanding , Let’s go back to XPathParser here , structure XPathParser:org.apache.ibatis.parsing.XPathParser#XPathParser(java.io.InputStream, boolean, java.util.Properties, org.xml.sax.EntityResolver)
Constructors :( stay XPathParser Class 123 Office )
// inputStream It's in our project mybatis Core profile , Such as :`D:\007\mybatis_demo01\target\classes\SqlMapperConfig.xml`
public XPathParser(InputStream inputStream, boolean validation, Properties variables, EntityResolver entityResolver) {
// This constructor initializes an internal property :javax.xml.xpath.XPath
commonConstructor(validation, variables, entityResolver);
// Initialize internal properties :org.w3c.dom.Document, Get one dom file
this.document = createDocument(new InputSource(inputStream));
}
6. Go back to 【2】 Step by step ,81 Row or so :
XPathParser When we understand the structure of , Go back to 【2】 Step , to glance at XMLConfigBuilder
The construction logic of
Code location XMLConfigBuilder:org.apache.ibatis.builder.xml.XMLConfigBuilder#XMLConfigBuilder(org.apache.ibatis.parsing.XPathParser, java.lang.String, java.util.Properties)
Actually called 85 Lines of code around the method :org.apache.ibatis.builder.xml.XMLConfigBuilder#XMLConfigBuilder(org.apache.ibatis.parsing.XPathParser, java.lang.String, java.util.Properties)
The method is as follows , Here’s a look at the first line of code Configuration The creation of :
private XMLConfigBuilder(XPathParser parser, String environment, Properties props) {
super(new Configuration());
ErrorContext.instance().resource("SQL Mapper Configuration");
// Set some properties
this.configuration.setVariables(props);
this.parsed = false;
this.environment = environment;
this.parser = parser;
}
Let’s take a closer look at the logic of this method .
6.1. first line super(new Configuration());
The first line calls the constructor of the parent class , namely :org.apache.ibatis.builder.BaseBuilder#BaseBuilder
public BaseBuilder(Configuration configuration) {
this.configuration = configuration;
this.typeAliasRegistry = this.configuration.getTypeAliasRegistry();
this.typeHandlerRegistry = this.configuration.getTypeHandlerRegistry();
}
6.2. Configuration Class is Mybatis The core configuration class , It’s so important !
Let’s take a look at the direct new The nonparametric constructor of the configuration information class : new 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);
}
What’s in it corresponds to what we are in mybatis Core profile (mybatis-config.xml) The property value configured in corresponds to the specific java Class mapping .
Configuration Class also defines a lot of properties , This is mainly about the analysis of loading process , Don’t expand on these properties , Just list a few instructions in the code comments below :
public class Configuration {
// Environment configuration :<environment id="dev">
protected Environment environment;
protected boolean safeRowBoundsEnabled;
protected boolean safeResultHandlerEnabled = true;
protected boolean mapUnderscoreToCamelCase;
protected boolean aggressiveLazyLoading;
protected boolean multipleResultSetsEnabled = true;
protected boolean useGeneratedKeys;
protected boolean useColumnLabel = true;
protected boolean cacheEnabled = true;
protected boolean callSettersOnNulls;
protected boolean useActualParamName = true;
protected boolean returnInstanceForEmptyRow;
// Prefix settings when outputting logs
protected String logPrefix;
// Specify the log implementation class ; Otherwise, it defaults to the order :SLF4J、Apache Commons Logging、Log4j 2、Log4j、JDK logging Find the implementation ;
protected Class <? extends Log> logImpl;
// Virtual file system , Will read interface Mapper.class file
protected Class <? extends VFS> vfsImpl;
// The default level 1 cache is session Level ( Another value is statement Level )
protected LocalCacheScope localCacheScope = LocalCacheScope.SESSION;
protected JdbcType jdbcTypeForNull = JdbcType.OTHER;
// When you call these methods , Late loaded objects are loaded before these methods are called
protected Set<String> lazyLoadTriggerMethods = new HashSet<String>(Arrays.asList(new String[] {
"equals", "clone", "hashCode", "toString" }));
protected Integer defaultStatementTimeout;
protected Integer defaultFetchSize;
// Default actuator type ,SIMPLE( Default ), REUSE, BATCH
protected ExecutorType defaultExecutorType = ExecutorType.SIMPLE;
// Set up mapper.xml The columns of the table in (column) and javabean Properties of (properties) The behavior of automatic mapping
protected AutoMappingBehavior autoMappingBehavior = AutoMappingBehavior.PARTIAL;
protected AutoMappingUnknownColumnBehavior autoMappingUnknownColumnBehavior = AutoMappingUnknownColumnBehavior.NONE;
protected Properties variables = new Properties();
protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
protected ObjectFactory objectFactory = new DefaultObjectFactory();
protected ObjectWrapperFactory objectWrapperFactory = new DefaultObjectWrapperFactory();
protected boolean lazyLoadingEnabled = false;
protected ProxyFactory proxyFactory = new JavassistProxyFactory(); // #224 Using internal Javassist instead of OGNL
protected String databaseId;
/**
* Configuration factory class.
* Used to create Configuration for loading deserialized unread properties.
*
* @see <a href='https://code.google.com/p/mybatis/issues/detail?id=300'>Issue 300 (google code)</a>
*/
protected Class<?> configurationFactory;
// Mapper registry : Using the proxy pattern ; By MapperProxy The agent creates the corresponding interface Mapper Instance
protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
// The interceptor chain , Inside list attribute interceptors Encapsulates all interceptor objects (org.apache.ibatis.plugin.Interceptor)
protected final InterceptorChain interceptorChain = new InterceptorChain();
// Type processor registry
protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
// Type alias registry
protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
// Language driver registry ( These objects generally refer to org.apache.ibatis.scripting.LanguageDriver Subclasses of )
// mybatis Default org.apache.ibatis.scripting.xmltags.XMLLanguageDriver type
protected final LanguageDriverRegistry languageRegistry = new LanguageDriverRegistry();
protected final Map<String, MappedStatement> mappedStatements = new StrictMap<MappedStatement>("Mapped Statements collection");
protected final Map<String, Cache> caches = new StrictMap<Cache>("Caches collection");
protected final Map<String, ResultMap> resultMaps = new StrictMap<ResultMap>("Result Maps collection");
protected final Map<String, ParameterMap> parameterMaps = new StrictMap<ParameterMap>("Parameter Maps collection");
protected final Map<String, KeyGenerator> keyGenerators = new StrictMap<KeyGenerator>("Key Generators collection");
protected final Set<String> loadedResources = new HashSet<String>();
protected final Map<String, XNode> sqlFragments = new StrictMap<XNode>("XML fragments parsed from previous mappers");
protected final Collection<XMLStatementBuilder> incompleteStatements = new LinkedList<XMLStatementBuilder>();
protected final Collection<CacheRefResolver> incompleteCacheRefs = new LinkedList<CacheRefResolver>();
protected final Collection<ResultMapResolver> incompleteResultMaps = new LinkedList<ResultMapResolver>();
protected final Collection<MethodResolver> incompleteMethods = new LinkedList<MethodResolver>();
/*
* A map holds cache-ref relationship. The key is the namespace that
* references a cache bound to another namespace and the value is the
* namespace which the actual cache is bound to.
*/
protected final Map<String, String> cacheRefMap = new HashMap<String, String>();
}
7. Go back to the first step SqlSessionFactoryBuilder#build
So far , It has been constructed XMLConfigBuilder Object .
Let’s go back to the first step org.apache.ibatis.session.SqlSessionFactoryBuilder#build(java.io.InputStream, java.lang.String, java.util.Properties)
, That is to say SqlSessionFactoryBuilder Class 75 Row or so .
Configuration object public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
try {
// parser It's got ;【 So far , It has been constructed XMLConfigBuilder Object .】
XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
// Start tracking here ....[parser.parse() obtain Configuration object ]
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.
}
}
}
7.1 see org.apache.ibatis.session.SqlSessionFactoryBuilder#build(org.apache.ibatis.session.Configuration)
Method
build(parser.parse())
This line of code calls this method :
public SqlSessionFactory build(Configuration config) {
return new DefaultSqlSessionFactory(config);
}
This method introduces a Configuration Object as parameter , This parameter we know is through parser.parse()
Got .
So pay attention to parser.parse()
.
7.2 parser.parse()
Method
In fact, that is :org.apache.ibatis.builder.xml.XMLConfigBuilder#parse
Method . stay XMLConfigBuilder
Class 94 Row or so .
public Configuration parse() {
if (parsed) {
// mybatis The core configuration file can only be loaded once
throw new BuilderException("Each XMLConfigBuilder can only be used once.");
}
parsed = true;
// It's using XPath Get root node : Namely config.xml The root node inside : `<configuration>`.
parseConfiguration(parser.evalNode("/configuration"));
return configuration;
}
parser.evalNode(“/configuration”) This line of code uses XPath Get root node : Namely config.xml The root node inside : <configuration>
.
7.3 And then execute this method XMLConfigBuilder#parseConfiguration
Take a look at this line of code parseConfiguration(parser.evalNode("/configuration"));
.
org.apache.ibatis.builder.xml.XMLConfigBuilder#parseConfiguration
, stay XMLConfigBuilder
Class 103 Row or so .
This method is parsing read mybatis-config.xml Each configuration item of the file , And assign it to configuration Go inside ( The bottom is configuration.setXXX Method setting ):
private void parseConfiguration(XNode root) {
try {
//issue #117 read properties first
propertiesElement(root.evalNode("properties"));
Properties settings = settingsAsProperties(root.evalNode("settings"));
loadCustomVfs(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
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);
}
}
Here we choose this line of code environmentsElement(root.evalNode("environments"));
Just follow up :
org.apache.ibatis.builder.xml.XMLConfigBuilder#environmentsElement
The method is as follows , You should be able to see some familiar words ( Configuration information of data source ):
private void environmentsElement(XNode context) throws Exception {
if (context != null) {
if (environment == null) {
environment = context.getStringAttribute("default");
}
for (XNode child : context.getChildren()) {
String id = child.getStringAttribute("id");
if (isSpecifiedEnvironment(id)) {
TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
DataSource dataSource = dsFactory.getDataSource();
Environment.Builder environmentBuilder = new Environment.Builder(id)
.transactionFactory(txFactory)
.dataSource(dataSource);
configuration.setEnvironment(environmentBuilder.build());
}
}
}
}
Is to get environments Node information :
<environments default="dev">
<environment id="dev">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
<environment id="test">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
This is it. MyBatis Core configuration object Configuration The main process of parsing and loading .