MyBatis entry series (2)-MyBatis global configuration file detailed 1

Global configuration file description

The configuration file mybatis-config.xml in the introductory case is the global configuration file of MyBatis, which contains all the related configuration items of MyBatis. These configurations will deeply affect the settings and attribute information of MyBatis behavior.

The top-level structure of the configuration file is as follows:

  • configuration
  • properties
  • settings
  • typeAliases (type aliases)
  • typeHandlers (type handlers)
  • objectFactory (object factory)
  • plugins
  • environments (environment configuration)
  • environment (environment variable)
  • transactionManager (transaction manager)
  • dataSource (data source)
  • databaseIdProvider (database vendor ID)
  • mappers

1. XML file header

<?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">
  1. version="1.0": The xml version used for the declaration is 1.0
  2. encoding="UTF-8": Declare the character encoding when transmitting data in xml. If there is Chinese in the document, the encoding method is not UTF-8, and the Chinese will be garbled if it is decoded after transmission.
  3. !DOCTYPE configuration: DOCTYPE is used to declare the document type and introduce DTD document type definition (Document Type Definition) constraints. This means that the external mybatis configuration file writing specification has been introduced for the label under the configuration label, and the configuration writing will be automatically prompted and verified.

2. configuration

The root tag of the configuration file, all configurations are in this tag.

<configuration>
	<!--mybatis配置...-->
</configuration>

3. properties

The main function of the properties tag is to introduce external properties and custom properties, and then use other configurations to introduce properties.

For example, configure database connection properties in an external file, and then introduce the use of properties in the data source configuration, so that configuration separation can be achieved. When you need to change it, you can directly change the external configuration file.

<properties resource="mysql.properties" url=""></properties>

The resource attribute represents the introduction of a local configuration file, and the url attribute represents the introduction of network resource configuration.

Use Cases

(1) Introduce an external file configuration attribute case

  1. Add the file mysql.properties under the resources directory
db.url=jdbc:mysql://127.0.0.1:3306/angel_admin?serverTimezone=Asia/Shanghai
db.driver=com.mysql.cj.jdbc.Driver
db.username=root
db.password=123456
  1. dataSource data source configuration uses ${} to introduce external property configuration
<?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="mysql.properties"/>
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <!--驱动名-->
                <property name="driver" value="${db.driver}"/>
                <!--数据库地址-->
                <property name="url"
                          value="${db.url}"/>
                <!--用户名-->
                <property name="username" value="${db.username}"/>
                <!--密码-->
                <property name="password" value="${db.password}"/>
            </dataSource>
        </environment>
    </environments>
    <!-- 添加mapper XML所在文件夹-->
    <mappers>
        <package name="org.pearl.mybatis.demo.dao"/>
    </mappers>
</configuration>

(2) Configure custom attribute case

  1. Add multiple property tags, configure database connection information
    <properties >
        <property name="db.driver" value="com.mysql.cj.jdbc.Driver"/>
        <property name="db.url" value="jdbc:mysql://127.0.0.1:3306/angel_admin?serverTimezone=Asia/Shanghai"/>
        <property name="db.username" value="root"/>
        <property name="db.password" value="123456"/>
    </properties>
  1. dataSource data source configuration uses ${} to introduce custom attributes

(3) Load sequence of multiple attributes with the same name

If a property is configured in more than one place, for example, db.driver is configured in the resource and property tags, then MyBatis will be loaded in the following order:

  1. First read the properties specified in the properties element body.
  2. Then read the property file under the classpath according to the resource attribute in the properties element, or read the property file according to the path specified by the url attribute, and overwrite the previously read property with the same name.
  3. Finally, read the attribute passed as the code method parameter, and overwrite the attribute of the same name that was read before.

Therefore, the attributes passed through the method parameters have the highest priority, the configuration file specified in the resource/url attribute is the next, and the attributes specified in the properties element have the lowest priority.

(4) The placeholder specifies the default value

Starting from MyBatis 3.4.2, you can specify a default value for the placeholder.

Case demonstration :

  1. This feature is turned off by default. To enable this feature, you need to add a specific attribute to enable this feature.
    <properties >
        <!-- 启用默认值特性 -->
        <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="true"/> 
    </properties>
  1. Use :the default value of the set property
            <dataSource type="POOLED">
                <!--驱动名-->
                <property name="driver" value="${db.driver:com.mysql.cj.jdbc.Driver}"/>
                <!--数据库地址-->
                <property name="url"
                          value="${db.url:jdbc:mysql://127.0.0.1:3306/angel_admin?serverTimezone=Asia/Shanghai}"/>
                <!--用户名-->
                <property name="username" value="${db.username:root}"/>
                <!--密码-->
                <property name="password" value="${db.password:123456}"/>
            </dataSource>
  1. When the configured attribute name also exists :(such as: db:username), there will be a conflict at this time, and you need to set a custom separator
    <properties >
        <!--添加自定义默认分隔符-->
        <property name="org.apache.ibatis.parsing.PropertyParser.enable-default-value" value="?:"/>
    </properties>

4. Settings

These are extremely important adjustment settings in MyBatis, and they will change the runtime behavior of MyBatis. The following table describes the meaning and default value of each setting in the settings.

Set namedescriptionEffective valueDefaults
cacheEnabledGlobally enable or disable any cache configured in all mapper configuration files.true /falsetrue
lazyLoadingEnabledGlobal switch for delayed loading. When turned on, all associated objects will be lazily loaded. In a specific association relationship, the on/off state of the item can be overridden by setting the fetchType property.true /falsefalse
aggressiveLazyLoadingWhen enabled, any method call will load all the lazy loading properties of the object. Otherwise, each lazy loading property will be loaded on demand (refer to lazyLoadTriggerMethods).true/falsefalse (default is true in 3.4.1 and earlier versions)
multipleResultSetsEnabledWhether to allow a single statement to return multiple result sets (requires database driver support).true / falsetrue
useColumnLabelUse column labels instead of column names. The actual performance depends on the database driver. For details, please refer to the related documents of the database driver or observe through comparative tests.true /falsetrue
useGeneratedKeysTo allow JDBC to support automatic generation of primary keys, database driver support is required. If set to true, it will force the use of automatically generated primary keys. Although some database drivers do not support this feature, they can still work (such as Derby).true / falseFalse
autoMappingBehaviorSpecify how MyBatis should automatically map columns to fields or attributes. NONE means to turn off automatic mapping; PARTIAL will only automatically map fields that do not define nested result mapping. FULL will automatically map any complex result set (whether nested or not).NONE, PARTIAL, FULLPARTIAL
autoMappingUnknownColumnBehaviorSpecify the behavior of discovering the unknown column (or unknown attribute type) of the automatic mapping target.NONE: Do nothing. WARNING: Output warning log ('org.apache.ibatis.session.AutoMappingUnknownColumnBehavior' log level must be set to WARN) FAILING: Mapping failed (throwing SqlSessionException) NONE, WARNING, FAILINGNONE
defaultExecutorTypeConfigure the default actuator. SIMPLE is an ordinary executor; REUSE executor reuses prepared statements (PreparedStatement); BATCH executor not only reuses statements but also performs batch updates.SIMPLE REUSE BATCHSIMPLE
defaultStatementTimeoutSet the timeout period, which determines the number of seconds the database driver waits for a response from the database.Any positive integerNot set (null)
defaultFetchSizeSet a recommended value for the driven result set fetch size (fetchSize). This parameter can only be overridden in the query settings.Any positive integerNot set (null)
defaultResultSetTypeSpecify the default scrolling strategy for the statement. (Added in 3.5.2)FORWARD_ONLY /SCROLL_SENSITIVE /SCROLL_INSENSITIVE/DEFAULT (equivalent to not set)Not set (null)
safeRowBoundsEnabledWhether to allow the use of paging (RowBounds) in nested statements. If it is allowed, set it to false.true/false False
safeResultHandlerEnabledWhether to allow the use of result handlers (ResultHandler) in nested statements. If allowed to use, set to false.true/falseTrue
mapUnderscoreToCamelCaseWhether to enable the automatic mapping of camel case names, that is, map from the classic database column name A_COLUMN to the classic Java property name aColumn.true /falseFalse
localCacheScopeMyBatis uses Local Cache to prevent circular references and speed up repeated nested queries. The default value is SESSION, which caches all queries executed in a session. If the setting value is STATEMENT, the local cache will only be used to execute statements, and different queries of the same SqlSession will not be cached.SESSION/STATEMENTSESSION
jdbcTypeForNullWhen no specific JDBC type is specified for the parameter, the default JDBC type for a null value. Some database drivers need to specify the JDBC type of the column. In most cases, you can directly use the general type, such as NULL, VARCHAR, or OTHER. JdbcType constant, commonly used values: NULL, VARCHAR or OTHER.OTHER
lazyLoadTriggerMethodsSpecify which methods of the object trigger a lazy loading.A comma-separated list of methods.equals,clone,hashCode,toString
defaultScriptingLanguageSpecify the default scripting language used for dynamic SQL generation.A type alias or fully qualified class name.org.apache.ibatis.scripting.xmltags.XMLLanguageDriver
defaultEnumTypeHandlerSpecify the default TypeHandler used by Enum.(New in 3.4.5) A type alias or fully qualified class name.org.apache.ibatis.type.EnumTypeHandler
callSettersOnNullsSpecifies whether to call the setter (put) method of the map object when the value in the result set is null. This is useful when relying on Map.keySet() or null values ​​for initialization. Note that the basic types (int, boolean, etc.) cannot be set to null.true/falsefalse
returnInstanceForEmptyRowWhen all the columns of the returned row are empty, MyBatis returns null by default. When this setting is turned on, MyBatis will return an empty instance. Note that it also applies to nested result sets (such as collections or associations). (Added in 3.4.2)true/ falsefalse
logPrefixSpecify the prefix MyBatis adds to the log name.Any stringNot set
logImplSpecify the specific implementation of the log used by MyBatis. If it is not specified, it will be automatically searched.SLF4J / LOG4J/ LOG4J2 /JDK_LOGGING/COMMONS_LOGGING /STDOUT_LOGGING/NO_LOGGINGNot set
proxyFactorySpecify the proxy tool used by Mybatis to create objects that can be lazily loaded.CGLIB/JAVASSISTJAVASSIST (MyBatis 3.3 and above)
vfsImplSpecify the implementation of VFSThe fully qualified class names of the implementation of the custom VFS, separated by commas.Not set
useActualParamNameIt is allowed to use the name in the method signature as the statement parameter name. In order to use this feature, your project must be compiled with Java 8 with the -parameters option. (Added in 3.4.1)true/ falsetrue
configurationFactorySpecify a class that provides an instance of Configuration. This returned Configuration instance is used to load the lazy loading property value of the deserialized object. This class must contain a method with the signature static Configuration getConfiguration().(New in 3.2.3) A type alias or fully qualified class name.Not set
shrinkWhitespacesInSqlRemove extra space characters from SQL. Please note that this also affects literal strings in SQL. (Added in 3.5.5)true/falsefalse
defaultSqlProviderTypeSpecify the sql provider class of the save provider method (since 3.5.6). When these attributes are omitted, this class will be applied to the type (or value) attribute on the sql provider annotation (for example @SelectProvider).A type alias or fully qualified class nameNot set

An example of a fully configured settings element is as follows:

<settings>
  <setting name="cacheEnabled" value="true"/>
  <setting name="lazyLoadingEnabled" value="true"/>
  <setting name="multipleResultSetsEnabled" value="true"/>
  <setting name="useColumnLabel" value="true"/>
  <setting name="useGeneratedKeys" value="false"/>
  <setting name="autoMappingBehavior" value="PARTIAL"/>
  <setting name="autoMappingUnknownColumnBehavior" value="WARNING"/>
  <setting name="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <setting name="defaultFetchSize" value="100"/>
  <setting name="safeRowBoundsEnabled" value="false"/>
  <setting name="mapUnderscoreToCamelCase" value="false"/>
  <setting name="localCacheScope" value="SESSION"/>
  <setting name="jdbcTypeForNull" value="OTHER"/>
  <setting name="lazyLoadTriggerMethods" value="equals,clone,hashCode,toString"/>
</settings>

Demonstration case :

In the database field naming convention, the underscore "_" is usually used to connect two words, such as user_type. However, in Java development, entity fields usually use camel case naming, so "AS" is used to set aliases to match entities in the SQL statement of the mapper file.

Mybatis has a mapUnderscoreToCamelCase parameter in the settings configuration item. Set it to True to enable automatic camel case naming rule mapping, that is, a similar mapping from the classic database column name A_COLUMN to the classic Java property name aColumn, the default is False.

  1. Add configuration under the settings tab
        <!--驼峰命名 自动将数据库字段下划线转为驼峰-->
        <setting name="mapUnderscoreToCamelCase" value="true"/>
  1. Getting started case SQL remove as
<select id="selectOneById" resultType="user">
    select * from base_user where user_id = #{id}
</select>
  1. Execute SQL and found that the conversion of underscore field to entity class camel case is automatically completed
Insert picture description here

5. Type aliases (typeAliases)

When setting the resultType of the SQL statement in the previous mapper XML, the fully qualified class name is written, which is relatively long, so Mybatis provides a type alias setting to set a short name for the Java type, which can facilitate us to refer to a certain class. When there are many classes, you can also set aliases for each class in this package in batches.

<mapper namespace="org.pearl.mybatis.demo.dao.UserMapper">
    <select id="selectOneById" resultType="org.pearl.mybatis.demo.pojo.entity.User">
    select * from base_user where user_id = #{id}
  </select>
</mapper>

After setting the alias, resultType can write the alias directly, which improves the simplicity.

<select id="selectOneById" resultType="user">
    select * from base_user where user_id = #{id}
</select>

(1) Use the typeAliases tag

typeAlias ​​can set an alias for a certain class.

package can specify a package name, MyBatis will search for the required Java Bean under the package name and set all aliases.

    <typeAliases>
        <!--单个类起别名-->
        <typeAlias type="org.pearl.mybatis.demo.pojo.entity.User" alias="user"/>
        <!--为某个包起别名 默认别名为类名小写-->
        <package name="org.pearl.mybatis.demo.pojo.entity"/>
    </typeAliases>

(2) Use @Aliasannotations

Use @Aliasannotations to mark the class and give it an alias.

@Data
@Alias("user")
public class User implements Serializable {

It is worth noting that MyBatis has built-in corresponding type aliases for many common Java types. They are all case-insensitive, and we must not use existing aliases when creating aliases.

Insert picture description here

6. Type Handlers (typeHandlers)

When MyBatis sets a parameter in a prepared statement (PreparedStatement) or retrieves a value from the result set, it will use a type processor to convert the obtained value into a Java type in a suitable way. For example, a field of the entity class is String, and in the database it will be VARCHAR. When rendezvous mapping between them, they need to be converted to their own type for processing.

Starting from 3.4.5, MyBatis supports JSR-310 (date and time API) by default. The previous version of MyBatis3.4 requires us to manually register these processors, and the later versions are automatically registered.

The following table describes some of the default type processors :

Type processorJava typeJDBC type
BooleanTypeHandlerjava.lang.Boolean, booleanDatabase compatible BOOLEAN
ByteTypeHandlerjava.lang.Byte, byteDatabase compatible NUMERIC or BYTE
ShortTypeHandlerjava.lang.Short, shortDatabase compatible NUMERIC or SMALLINT
IntegerTypeHandlerjava.lang.Integer, intDatabase compatible NUMERIC or INTEGER
LongTypeHandlerjava.lang.Long, longDatabase compatible NUMERIC or BIGINT
FloatTypeHandlerjava.lang.Float, floatDatabase compatible NUMERIC or FLOAT
DoubleTypeHandlerjava.lang.Double, doubleDatabase compatible NUMERIC or DOUBLE
BigDecimalTypeHandlerjava.math.BigDecimalDatabase compatible NUMERIC or DECIMAL
StringTypeHandlerjava.lang.StringCHAR, VARCHAR
ClobReaderTypeHandlerjava.io.Reader-
ClobTypeHandlerjava.lang.StringCLOB, LONGVARCHAR
NStringTypeHandlerjava.lang.StringNVARCHAR, NCHAR
NClobTypeHandlerjava.lang.StringNCLOB
BlobInputStreamTypeHandlerjava.io.InputStream-
ByteArrayTypeHandlerbyte[]Database compatible byte stream type
BlobTypeHandlerbyte[]BLOB, LONGVARBINARY
DateTypeHandlerjava.util.DateTIMESTAMP
DateOnlyTypeHandlerjava.util.DateDATE
TimeOnlyTypeHandlerjava.util.DateTIME
SqlTimestampTypeHandlerjava.sql.TimestampTIMESTAMP
SqlDateTypeHandlerjava.sql.DateDATE
SqlTimeTypeHandlerjava.sql.TimeTIME
ObjectTypeHandlerAnyOTHER or unspecified type
EnumTypeHandlerEnumeration TypeVARCHAR or any compatible string type, used to store the name of the enumeration (not the index ordinal value)
EnumOrdinalTypeHandlerEnumeration TypeAny compatible NUMERIC or DOUBLE type, used to store the ordinal value (not the name) of the enumeration.
SqlxmlTypeHandlerjava.lang.StringSQLXML
InstantTypeHandlerjava.time.InstantTIMESTAMP
LocalDateTimeTypeHandlerjava.time.LocalDateTimeTIMESTAMP
LocalDateTypeHandlerjava.time.LocalDateDATE
LocalTimeTypeHandlerjava.time.LocalTimeTIME
OffsetDateTimeTypeHandlerjava.time.OffsetDateTimeTIMESTAMP
OffsetTimeTypeHandlerjava.time.OffsetTimeTIME
ZonedDateTimeTypeHandlerjava.time.ZonedDateTimeTIMESTAMP
YearTypeHandlerjava.time.YearINTEGER
MonthTypeHandlerjava.time.MonthINTEGER
YearMonthTypeHandlerjava.time.YearMonthVARCHAR or LONGVARCHAR
JapaneseDateTypeHandlerjava.time.chrono.JapaneseDateDATE

You can rewrite the existing type processor or create your own type processor to deal with unsupported or non-standard types. Enumerated types should be used the most.

Case demonstration :

  1. Write a type processor (it will overwrite the existing type processor that handles Java String type attributes and VARCHAR type parameters and results).
/**
 * Created by TD on 2021/6/9
 * 类型处理器: String《=》VARCHAR
 * 实现org.apache.ibatis.type.TypeHandler接口或者继承org.apache.ibatis.type.BaseTypeHandler
 * MappedJdbcTypes: 指定数据库的数据类型
 * BaseTypeHandler泛型: 指定JAVA数据类型
 */
@MappedJdbcTypes(JdbcType.VARCHAR)
public class ExampleTypeHandler extends BaseTypeHandler<String> {

    /**
     * javaType转换成jdbcTpe
     */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, parameter);
    }

    /**
     *  将从结果集根据列名称获取到的数据的jdbcType转换成javaType
     */
    @Override
    public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return rs.getString(columnName);
    }

    /**
     * 将从结果集根据列索引获取到的数据的jdbcType转换成javaType
     */
    @Override
    public String getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return rs.getString(columnIndex);
    }

    /**
     *  存储过程
     */
    @Override
    public String getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return cs.getString(columnIndex);
    }
}

  1. Register the processor in the mybatis global configuration file, or by scanning the processor under the package
    <!--类型处理器-->
    <typeHandlers>
        <typeHandler handler="org.pearl.mybatis.demo.handler.ExampleTypeHandler"/>
    </typeHandlers>
<typeHandlers>
  <package name="org.pearl.mybatis.demo.handler"/>
</typeHandlers>

MyBatis does not determine which type to use by detecting database meta-information, so you must indicate that the field is of VARCHAR type in the parameter and result mapping so that it can be bound to the correct type processor. This is because MyBatis does not know the data type until the statement is executed.

Through the generic type of the type processor, MyBatis can know the type of Java handled by the type of processor, but this behavior can be changed in two ways:

  • Add a javaType attribute (for example: javaType="String") to the configuration element (typeHandler element) of the type processor;
  • Add a @MappedTypes annotation to the class of the type processor to specify the list of Java types associated with it. If it is also specified in the javaType attribute, the configuration on the annotation will be ignored.

There are two ways to specify the associated JDBC type:

  • Add a jdbcType attribute to the configuration element of the type processor (for example: jdbcType="VARCHAR");
  • Add a @MappedJdbcTypes annotation to the class of the type processor to specify the list of JDBC types associated with it. If it is also specified in the jdbcType attribute, the configuration on the annotation will be ignored.

Processing enumeration type
If you want to map the enumeration type Enum, you need to choose one from EnumTypeHandler or EnumOrdinalTypeHandler to use.

For example, we want to store the rounding mode used when approximating the value. By default, MyBatis will use EnumTypeHandler to convert Enum values ​​into corresponding names.

<!-- mybatis-config.xml -->
<typeHandlers>
  <typeHandler handler="org.apache.ibatis.type.EnumOrdinalTypeHandler" javaType="java.math.RoundingMode"/>
</typeHandlers>