One 、 On Configuration class

So let's see MyBatis Of XML Configuration file structure ,( Excerpt from

This is Configuration Part of the variables of the class

It's not the same, is it ???

Actually Configuration Class is created by XMLConfigBuilder( Inherited from BaseBuilder class ) From analysis , By the following method (parseConfiguration) analysis

 private void parseConfiguration(XNode root) {
try {
Properties settings = settingsAsPropertiess(root.evalNode("settings"));
//issue #117 read properties first
// read it after objectFactory and objectWrapperFactory issue #631
} catch (Exception e) {
throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: " + e, e);

The caller of this method is of the same class parse() Method , It was mentioned in the first note ,SqlSessionFactoryBuilder Class is responsible for building SqlSessionFactory, One of the important steps is to parse the configuration file , It's this that's called parse() Method , The call chain is as follows :

go back to parseConfiguration Method , This method is responsible for XML The information in the file resolves to Configuration Class , Make it one by one , Here's the last one mapperElement(root.evalNode("mappers")) The implementation of the , Responsible for reading <mappers> node , Other methods work the same way

Configuration Class is like MyBatis My manager , It contains all the information , Some properties are not set and will not affect configuration The construction of , because MyBatis Default values are assigned to these properties , In order to make sure MyBatis Be able to function .

  Two 、 Each configuration analysis

 1. properties Global parameter

Official example

<properties resource="org/mybatis/example/">
<property name="username" value="dev_user"/>
<property name="password" value="F2Fa3!33TYyg"/>
</properties> properties Parameters from propertiesElement() Method , The method is as follows :
private void propertiesElement(XNode context) throws Exception {
if (context != null) {
Properties defaults = context.getChildrenAsProperties();
String resource = context.getStringAttribute("resource");
String url = context.getStringAttribute("url");
// Be careful ,resource Properties and url Attributes cannot exist at the same time , Otherwise, an unresolved exception will be thrown
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.");
// The properties read later will override the existing ones , because properties Inherited from HashTable, Or key value pairs , after put The value of will override the previous put In value
if (resource != null) {
} else if (url != null) {
// If Configuration In the object variables Property is not empty , Then add it to properties In the object
Properties vars = configuration.getVariables();
if (vars != null) {
// Finally, save these parameters to Configuration In the object

From the above information, we can conclude that :

Set by code configuration Parameters have the highest priority , Because it's the last side of the method that puts those values put In the , Then is properties The child node has the lowest priority , First recorded , It's also the easiest to override by the following parameters , therefore , If you read an external file (resource perhaps url The way ), The child node should not be repeated with other parameters .


<!-- Enable L2 cache -->
<setting name="cacheEnabled" value="true" />
<!-- Turn on delay loading -->
<setting name="lazyLoadingEnabled" value="true" />

<!-- When enabled , A call to an arbitrary lazy property causes the object with the lazy load property to be fully loaded , conversely , Each property is loaded on demand -->

<setting name="aggressiveLazyLoading" value="true" />

settings First of all, by settingsAsPropertiess() The method is resolved into properties object , And then by loadCustomVfs() Methods and settingsElement() Methods analyze respectively , The implementation is as follows :
// This method is used to put settings The node resolves into properties object 
private Properties settingsAsPropertiess(XNode context) {
if (context == null) {
return new Properties();
Properties props = context.getChildrenAsProperties();
// Check that all settings are known to the configuration class
MetaClass metaConfig = MetaClass.forClass(Configuration.class, localReflectorFactory);
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;
} //VFS It means virtual file system ; Mainly through the program can be convenient to read the local file system 、FTP File resources in a system such as a file system .
//Mybatis Provided in VFS This configuration , It is mainly through this configuration that custom virtual file system applications can be loaded .
//VFS It's singleton mode , If you are interested, you can learn something about it
private void loadCustomVfs(Properties props) throws ClassNotFoundException {
String value = props.getProperty("vfsImpl");
if (value != null) {
String[] clazzes = value.split(",");
for (String clazz : clazzes) {
if (!clazz.isEmpty()) {
} // Handle each set child node , If it is not set, the default value will be set
private void settingsElement(Properties props) throws Exception {
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"), true));
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.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.setCallSettersOnNulls(booleanValueOf(props.getProperty("callSettersOnNulls"), false));
3.typeAliases Alias 
Type alias is for Java Type to set a short name . It's only with XML Configure the , It exists only to reduce the redundancy of fully qualified names of classes .
It also has one <package name="com.ys.po" /> label , In the absence of annotations , Will use Bean The first and lowercase unqualified class name is used as its alias
After configuring the type alias, we use resulttype="Alias" You don't have to have a full name , Very convenient .
We can define our own aliases , Most of them are their own entity classes ,MyBatis Also set up an alias for us by default ( Most of them TypeAliasRegistry.class in ), Including common int,byte Other types , also settings Some of them value value , such as LRU etc. , Detailed alias settings can refer to the official , The official website is very detailed , Again, I won't repeat it , Here's a post Configuration Alias set by constructor .
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);

summary :

Whether it's through package Label configuration , Or through typeAlias Alias for tag configuration , stay mapper.xml When used in files , Converting to lowercase is equal , Then you can use it .

If you don't set the alias manually , The default is lowercase for the class name .

If the annotation alias is configured , The annotation alias will override all the above configurations .

4.typeHandler Type processor 
Because the database may come from different manufacturers , The parameters set by different manufacturers may be different , At the same time, the database can also customize the type ,typeHandler Allows you to customize settings based on your project needs java Parameters passed to the database , Or read data from a database , We also need special treatment, which can be done in typeHandler To realize , Especially enumeration .
To put it bluntly ,typehandler Is to complete the database type and java Conversion of types , And typeAliases equally ,typehandler It is also divided into system definition and user definition , Generally speaking , The system defined type processor can do most of the functions .
The following are system defined processors :
private void typeHandlerElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
if ("package".equals(child.getName())) {
String typeHandlerPackage = child.getStringAttribute("name");
} 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.calss Class , They are all common types :

public TypeHandlerRegistry() {
register(Boolean.class, new BooleanTypeHandler());
register(boolean.class, new BooleanTypeHandler());
register(JdbcType.BOOLEAN, new BooleanTypeHandler());
register(JdbcType.BIT, new BooleanTypeHandler()); register(Byte.class, new ByteTypeHandler());
register(byte.class, new ByteTypeHandler());
register(JdbcType.TINYINT, new ByteTypeHandler()); register(Short.class, new ShortTypeHandler());
register(short.class, new ShortTypeHandler());
register(JdbcType.SMALLINT, new ShortTypeHandler()); register(Integer.class, new IntegerTypeHandler());
register(int.class, new IntegerTypeHandler());
register(JdbcType.INTEGER, new IntegerTypeHandler()); register(Long.class, new LongTypeHandler());
register(long.class, new LongTypeHandler()); register(Float.class, new FloatTypeHandler());
register(float.class, new FloatTypeHandler());
register(JdbcType.FLOAT, new FloatTypeHandler()); register(Double.class, new DoubleTypeHandler());
register(double.class, new DoubleTypeHandler());
register(JdbcType.DOUBLE, new DoubleTypeHandler()); register(Reader.class, new ClobReaderTypeHandler());
register(String.class, new StringTypeHandler());
register(String.class, JdbcType.CHAR, new StringTypeHandler());
register(String.class, JdbcType.CLOB, new ClobTypeHandler());
register(String.class, JdbcType.VARCHAR, new StringTypeHandler());
register(String.class, JdbcType.LONGVARCHAR, new ClobTypeHandler());
register(String.class, JdbcType.NVARCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCHAR, new NStringTypeHandler());
register(String.class, JdbcType.NCLOB, new NClobTypeHandler());
register(JdbcType.CHAR, new StringTypeHandler());
register(JdbcType.VARCHAR, new StringTypeHandler());
register(JdbcType.CLOB, new ClobTypeHandler());
register(JdbcType.LONGVARCHAR, new ClobTypeHandler());
register(JdbcType.NVARCHAR, new NStringTypeHandler());
register(JdbcType.NCHAR, new NStringTypeHandler());
register(JdbcType.NCLOB, new NClobTypeHandler()); register(Object.class, JdbcType.ARRAY, new ArrayTypeHandler());
register(JdbcType.ARRAY, new ArrayTypeHandler()); register(BigInteger.class, new BigIntegerTypeHandler());
register(JdbcType.BIGINT, new LongTypeHandler()); register(BigDecimal.class, new BigDecimalTypeHandler());
register(JdbcType.REAL, new BigDecimalTypeHandler());
register(JdbcType.DECIMAL, new BigDecimalTypeHandler());
register(JdbcType.NUMERIC, new BigDecimalTypeHandler()); register(InputStream.class, new BlobInputStreamTypeHandler());
register(Byte[].class, new ByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.BLOB, new BlobByteObjectArrayTypeHandler());
register(Byte[].class, JdbcType.LONGVARBINARY, new BlobByteObjectArrayTypeHandler());
register(byte[].class, new ByteArrayTypeHandler());
register(byte[].class, JdbcType.BLOB, new BlobTypeHandler());
register(byte[].class, JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.LONGVARBINARY, new BlobTypeHandler());
register(JdbcType.BLOB, new BlobTypeHandler()); register(Object.class, UNKNOWN_TYPE_HANDLER);
register(Object.class, JdbcType.OTHER, UNKNOWN_TYPE_HANDLER);
register(JdbcType.OTHER, UNKNOWN_TYPE_HANDLER); register(Date.class, new DateTypeHandler());
register(Date.class, JdbcType.DATE, new DateOnlyTypeHandler());
register(Date.class, JdbcType.TIME, new TimeOnlyTypeHandler());
register(JdbcType.TIMESTAMP, new DateTypeHandler());
register(JdbcType.DATE, new DateOnlyTypeHandler());
register(JdbcType.TIME, new TimeOnlyTypeHandler()); register(java.sql.Date.class, new SqlDateTypeHandler());
register(java.sql.Time.class, new SqlTimeTypeHandler());
register(java.sql.Timestamp.class, new SqlTimestampTypeHandler()); // mybatis-typehandlers-jsr310
try {
register("java.time.Instant", "org.apache.ibatis.type.InstantTypeHandler");
register("java.time.LocalDateTime", "org.apache.ibatis.type.LocalDateTimeTypeHandler");
register("java.time.LocalDate", "org.apache.ibatis.type.LocalDateTypeHandler");
register("java.time.LocalTime", "org.apache.ibatis.type.LocalTimeTypeHandler");
register("java.time.OffsetDateTime", "org.apache.ibatis.type.OffsetDateTimeTypeHandler");
register("java.time.OffsetTime", "org.apache.ibatis.type.OffsetTimeTypeHandler");
register("java.time.ZonedDateTime", "org.apache.ibatis.type.ZonedDateTimeTypeHandler");
} catch (ClassNotFoundException e) {
// no JSR-310 handlers
} // issue #273
register(Character.class, new CharacterTypeHandler());
register(char.class, new CharacterTypeHandler());

5.mappers mapper

Mapper is MyBatis The most complicated 、 The core component .

Mapper provides DAO Layer interface to mapper.xml Mapping of files , We just need to call DAO Layer method , You can perform the corresponding SQL sentence , Here's what I'm using java Dynamic proxy features of , So let's see config The configuration file is in mapper Set up :

<!-- Using classpath relative resources -->
<mapper resource="org/mybatis/builder/AuthorMapper.xml"/>
<mapper resource="org/mybatis/builder/BlogMapper.xml"/>
<mapper resource="org/mybatis/builder/PostMapper.xml"/>
<!-- Using url fully qualified paths -->
<mapper url="file:///var/mappers/AuthorMapper.xml"/>
<mapper url="file:///var/mappers/BlogMapper.xml"/>
<mapper url="file:///var/mappers/PostMapper.xml"/>
<!-- Using mapper interface classes -->
<mapper class="org.mybatis.builder.AuthorMapper"/>
<mapper class="org.mybatis.builder.BlogMapper"/>
<mapper class="org.mybatis.builder.PostMapper"/>
<!-- Register all interfaces in a package as mappers -->
<package name="org.mybatis.builder"/>

Let's take a look at the source code :

 private void mapperElement(XNode parent) throws Exception {
if (parent != null) {
for (XNode child : parent.getChildren()) {
// First judgement pckage Whether the subelements exist , To be is to analyze , commonly package With a few
if ("package".equals(child.getName())) {
String mapperPackage = child.getStringAttribute("name");
} else {
// The point is this else The analysis inside , Resolve separately resource,url,class
String resource = child.getStringAttribute("resource");
String url = child.getStringAttribute("url");
String mapperClass = child.getStringAttribute("class");
// From the bottom if...else... It can be seen that ,resource,url,class There can only be one of the three attributes , Otherwise, an exception will be thrown
if (resource != null && url == null && mapperClass == null) {
InputStream inputStream = Resources.getResourceAsStream(resource);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, resource, configuration.getSqlFragments());
// The one we use most often is resource attribute , Now let's go back to this parse() Method
} else if (resource == null && url != null && mapperClass == null) {
InputStream inputStream = Resources.getUrlAsStream(url);
XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, url, configuration.getSqlFragments());
} else if (resource == null && url == null && mapperClass != null) {
Class<?> mapperInterface = Resources.classForName(mapperClass);
} else {
throw new BuilderException("A mapper element may only specify a url, resource or class, but not more than one.");

resource It's in there mapper.xml file ,MyBatis According to this xml File to parse it DAO Layer interface , And the inside SQL Statement and corresponding settings , Here is parse() Source code :

 public void parse() {
if (!configuration.isResourceLoaded(resource)) {
// This parsing mapper The elements in it , such as cache-ref、parameterMap、resultMap、sql、select|insert|update|delete etc.
// This method is based on namespace Put this mapper and DAO Layer interfaces
// It will be analyzed separately ..., See the name and know the meaning
 This parse() It's more complicated , Especially for resultMap Parsing of tags , And for  select|insert|update|delete Parsing of tags , In the future, we may focus on .

 6. Several other configurations


When MyBatis When building a result return , Will use objectFactory To build POJO, Of course , We can also customize our own object factory , But generally speaking , It's enough to use the default .


plug-in unit , For example, paging plug-ins and so on , This is more complicated , Be very careful when using it , Using the plug-in will override some MyBatis The behavior of internal core objects , Finally, I can understand MyBatis After the internal operation principle is used .


Data source configuration , Multiple data sources can be configured , And transaction configuration , I will explain it in detail later


Generally, database vendor identification is less used , Because the possibility of our system running in two database vendors at the same time is relatively small .


MyBatis Learning notes ( 3、 ... and ) Configuration Class

  1. MyBatis Learning notes ( 3、 ... and ) Connections

    First of all, I would like to recommend a few web pages :  Nothing to see - MyBatis Tools h ...

  2. mybatis Learning notes 3 ( Connections )

    Study mybatis Correlation relation of , The main annotation is on the code , No explanation here . Don't post the same configuration file 1. Association table creation ( Students correspond to teachers For one more ) Students, teachers, tables 2. The entity class corresponding to the table package com.home.en ...

  3. MyBatis Learning notes ( 3、 ... and )—— Optimize MyBatis Configuration in profile

    From lonely Wolf's blog : One . The configuration to connect to the database is placed in a separate properties In file Before , We're going directly to the database ...

  4. Mybatis Learning notes ( 3、 ... and ) —— DAO development method

    One .SqlSession Application scope of SqlSession Encapsulates the operation of the database , Such as : Inquire about . Insert . to update . Delete etc. . SqlSession adopt SqlSessionFactory establish . SqlSessionF ...

  5. ( turn )Qt Model/View Learning notes ( 3、 ... and )——Model class

    Model class Basic concepts stay model/view In architecture ,model by view and delegates Using data provides a standard interface . stay Qt in , Standard interface QAbstractItemModel Class . No matter the data is at the bottom with ...

  6. mybatis Learning notes ( 3、 ... and )-- Optimize database connection configuration

    Originally, the database connection configuration information was directly written in conf.xml Configuration in progress , as follows <?xml version="1.0" encoding="UTF-8"?> < ...

  7. SpringMVC + Spring + MyBatis Learning notes : Use... On both classes and methods RequestMapping How to access the

    System :WIN8.1 database :Oracle 11GR2 development tool :MyEclipse 8.6 frame :Spring3.2.9.SpringMVC3.2.9.MyBatis3.2.8 Look at the code first : @Requ ...

  8. Mybatis Learning notes 3

    One . Delay loading Delayed loading means delayed loading , It's not loaded all at once, it's loaded on demand , I think it should be for multi table query , That is to query the information of a single table before loading it , This can improve the performance of the database : It should be noted that ,mybatis Provide ...

  9. JVM Learning notes ( 3、 ... and ): Class file structure

    The result of code compilation changes from local machine code to bytecode , It's a small step in the development of storage formats , It's a big step in the development of programming languages . The basis of language independence is virtual machine and byte code storage format .Java Virtual machines do not include Java Any language binding within , Only with &quo ...

Random recommendation

  1. slide effect

    html and js part <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://w ...

  2. compile OpenJDK The notes

    1.  ERROR: You seem to not have installed ALSA 0.9.1 or higher. No need to ALSA Download from the official website alsa-dev and alsa-drive, ubu ...

  3. Myeclipse Operating the database

    step 1: adopt MyEclipse Medium window->show View->other Call out .DB browser , and SQL Results step 2. You can right-click in the space , choice new, Create a new DB ...

  4. [ Reprint ] understand HTML semantic

    Statement : This article is reproduced in :freeyiyi1993 Blog . Original address : 1. What is? HTML semantic ? < ...

  5. lightoj 1013

    Ideas : Dynamic programming . set up dp[i][j][k] It means to use the front of the first string i The interval character and the front of the second string k The interval length is i The number of strings of , that : if s1[j+1] == s2[k+1] dp[i+1][j+1][k+1] += ...

  6. apache pdfbox

    turn Easy to use apache pdfbox take pdf File generation diagram In the near future in the project ...

  7. Python import / pyd / dll

    Use Python import When the module , First, we will search in the module path Search in turn for ( The module with the same name will be overridden before ), The order is : 1. The main directory of the program ( The current working directory or The directory where the script file is located ) 2. Environmental Science ...

  8. hdu4635( How many sides at most , Let a digraph be not a strongly connected graph )

    At the end of the line, there must be two sets x,yx Each element of the collection , To y Each element in the collection is a one-way edge x aggregate , and y All sets are complete graphs a by x The number of points in the set , b by y So the answer is a * b + a*(a-1) + b*( ...

  9. Follow brother gang java Knowledge point —— Multithreading ( sixteen )

    The first way to create multithreading :① Inherit : Inherit Thread.② rewrite : rewrite Thread Class run() Method ③ establish : Create a subclass object ④ call : Calling thread's start() Method , Start this thread , call run() Method cla ...

  10. MySQL Technology insider book notes ( 8、 ... and )—— Business

    Implementation of transactions ​ Transaction isolation is achieved by locks . Atomicity . Uniformity . Persistence through database redo log and undo log To complete .redo log Called redo log , To ensure the atomicity and persistence of transactions .undo log To make sure that ...