Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

MyBatis XML configuration


May 16, 2021 MyBatis


Table of contents


XML mapping profile

MyBatis's profile contains settings and properties that affect myBatis's behavior.

properties

These properties are externally configurable and dynamically replaceable, available neither in a typical Java property file nor passed through the child elements of the properties element. For example:

<properties resource="org/mybatis/example/config.properties">
  <property name="username" value="dev_user"/>
  <property name="password" value="F2Fa3!33TYyg"/>
</properties>

The properties can be used throughout the profile to replace property values that need to be dynamically configured. Like what:

<dataSource type="POOLED">
  <property name="driver" value="${driver}"/>
  <property name="url" value="${url}"/>
  <property name="username" value="${username}"/>
  <property name="password" value="${password}"/>
</dataSource>

The username and password in this example will be replaced by the appropriate values set in the properties element. T he driver and url properties will be replaced by the values corresponding to the config.properties file. This provides a number of flexible options for configuration.

Properties can also be passed to the SqlSessionBuilder.build() method. For example:

    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, props);

    // ... or ...

    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment, props);

If the property is configured in more than one place, MyBatis loads in the following order:

  • The properties specified inside the properties element are read first.
  • The property file under the class path is then read according to the resource property in the properties element, or the property file is read according to the path specified by the url property, and the property with the same name that has been read is overwritten.
  • The property passed as a method argument is finally read and overrides the property with the same name that has been read.

Therefore, properties passed through method parameters have the highest priority, second to the profile specified in the resource/url property, and the lowest priority is the property specified in the properties property.

settings

This is an extremely important adjustment setting in MyBatis that changes MyBatis' runtime behavior. The following table describes the intent, default values, and so on for each item in the settings.

Set the parameters Describe The valid value The default
cacheEnabled This configuration affects the global switch of the cache configured in all map factors. true,false true
lazyLoadingEnabled A global switch that delays loading. W hen on, all associated objects are delayed loading. In a particular association, the switch state of the item can be overwritten by setting the fetchType property. true,false false
aggressiveLazyLoading When enabled, a call to any delayed property causes the object with the deferred load property to load completely; true,false
multipleResultSetsEnabled Whether to allow a single statement to return a multi-result set (compatibility drive required). true,false true
useColumnLabel Use column labels instead of column names. Different drivers will behave differently in this regard, referred to the relevant driver documentation or by testing these two different modes to observe the results of the drivers used. true,false true
useGeneratedKeys Allowing JDBC to support the automatic generation of primary keys requires driver compatibility. If set to true, this setting forces the automatic generation of primary keys, which work even though some drivers are not compatible (such as Derby). true,false False
autoMappingBehavior Specify how MyBatis should automatically map columns to fields or properties. N ONE means unmapped automatically; PARTIAL automatically maps only the result set that does not have a nested result set map defined. FULL automatically maps any complex set of results, whether nested or not. NONE, PARTIAL, FULL PARTIAL
defaultExecutorType Configure the default executor. SIMPLE is a normal executor; reuse executors reuse preprocessed statements; BATCH executors reuse statements and perform bulk updates. SIMPLE REUSE BATCH SIMPLE
defaultStatementTimeout Set the timeout, which determines the number of seconds that drive the wait for the database to respond. Any positive integer Not Set (null)
safeRowBoundsEnabled Allows the use of RowBounds in nested statements. true,false False
mapUnderscoreToCamelCase Whether to turn on automatic hump naming rule mapping, a similar mapping from the classic database column name A_COLUMN to the classic Java property name aColumn. true, false False
localCacheScope MyBatis uses the Local Cache mechanism to prevent circular references and speed up repeated nested queries. T he default is SESSION, in which case all queries executed in a session are cached. If you set the value to STATEMENT, the local session is used only for statement execution, and different calls to the same SqlSesion will not share data. SESSION,STATEMENT SESSION
jdbcTypeForNull When a specific JDBC type is not provided for the parameter, the JDBC type is specified for the empty value. Some drivers require the JDBC type of the specified column, most of which can be used directly with a general type, such as NULL, VARCHAR, or OTHER. JdbcType enumeration. Most common are: NULL, VARCHAR and OTHER OTHER
lazyLoadTriggerMethods The method that specifies which object triggers a lazy load. A method name list separated by commas equals,clone,hashCode,toString
defaultScriptingLanguage Specifies the default language for dynamic SQL generation. A type alias or fully qualified class name. org.apache.ibatis.scripting.xmltags.XMLDynamicLanguageDriver
callSettersOnNulls It is useful to specify whether the setter method of the mapping object is called when the result set value is null, which is useful when there is a Map.keySet() dependency or null value initialization. Note that the base type (int, boolean, etc.) cannot be set to null. true,false false
logPrefix Specify the prefix that MyBatis adds to the log name. Any String Not set
logImpl Specify the specific implementation of the log used by MyBatis, which will be looked up automatically when not specified. SLF4J,LOG4J,LOG4J2,JDK_LOGGING,COMMONS_LOGGING,STDOUT_LOGGING,NO_LOGGING Not set
proxyFactory

Specifies the proxy tool used by Mybatis to create objects with late load capabilities. CGLIB JAVASSIST CGLIB

vfslmpl

Specifies the implementation of VFS The class of the implementation of the custom VFS is fully qualified and separated by a comma. no set

useActualParamName

The name in the method signature is allowed as the statement argument name. I n order to use this feature, your project must be compiled in Java 8, with -parameters option. (Added to 3.4.1) true | false true

configurationFactory

Specify a class that Configuration instance. T his returned Configuration instance is used to load the lazy load property value of the antiserated object. T his class must contain a method static Configuration getConfiguration() (Added to 3.2.3) Type alias or full class name. no 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="defaultExecutorType" value="SIMPLE"/>
  <setting name="defaultStatementTimeout" value="25"/>
  <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>

typeAliases

The type alias is a short name for the Java type. I t is only related to XML configuration, and its meaning is only used to reduce redundancy of fully qualified names for classes. For example:

<typeAliases>
  <typeAlias alias="Author" type="domain.blog.Author"/>
  <typeAlias alias="Blog" type="domain.blog.Blog"/>
  <typeAlias alias="Comment" type="domain.blog.Comment"/>
  <typeAlias alias="Post" type="domain.blog.Post"/>
  <typeAlias alias="Section" type="domain.blog.Section"/>
  <typeAlias alias="Tag" type="domain.blog.Tag"/>
</typeAliases>

When configured in this way, Blog can be used domain.blog.Blog use.

You can also specify a package name, under which MyBatis searches for the Java Beans you need, such as:

<typeAliases>
  <package name="domain.blog"/>
</typeAliases>

Each Java bean domain.blog package, without annotations, uses the bean's initials lowercase unqualified class name as its alias. domain.blog.Author alias author Take a look at the following example:

    @Alias("author")
    public class Author {
        ...
    }

Appropriate type aliases have been built into many common Java types. They are all case insensitive, and it is important to note that special handling is caused by the repetition of the base type name.

Alias Mapping type
_byte byte
_long long
_short short
_int int
_integer int
_double double
_float float
_boolean boolean
string String
byte Byte
long Long
short Short
int Integer
integer Integer
double Double
float Float
boolean Boolean
date Date
decimal BigDecimal
bigdecimal BigDecimal
object Object
map Map
hashmap HashMap
list List
arraylist ArrayList
collection Collection
iterator Iterator

typeHandlers

Whether MyBatis sets a parameter in a prepared statement or takes a value out of the result set, the type processor converts the obtained value into a Java type in an appropriate way. The following table describes some of the default type processors.

Type processor Java type JDBC type
BooleanTypeHandler java.lang.Boolean , boolean Database-compatible BOOLEAN
ByteTypeHandler java.lang.Byte , byte Database-compatible NUMERIC or BYTE
ShortTypeHandler java.lang.Short , short Database-compatible NUMERIC or SHORT INTEGER
IntegerTypeHandler java.lang.Integer , int Database-compatible NUMERIC INTEGER
LongTypeHandler java.lang.Long , long Database-compatible NUMERIC or LONG INTEGER
FloatTypeHandler java.lang.Float , float Database-compatible NUMERIC or FLOAT
DoubleTypeHandler java.lang.Double , double Database-compatible NUMERIC or DOUBLE
BigDecimalTypeHandler java.math.BigDecimal Database-compatible NUMERIC DECIMAL
StringTypeHandler java.lang.String CHAR , VARCHAR
ClobTypeHandler java.lang.String CLOB , LONGVARCHAR
NStringTypeHandler java.lang.String NVARCHAR , NCHAR
NClobTypeHandler java.lang.String NCLOB
ByteArrayTypeHandler byte[] The type of byte stream that the database is compatible with
BlobTypeHandler byte[] BLOB , LONGVARBINARY
DateTypeHandler java.util.Date TIMESTAMP
DateOnlyTypeHandler java.util.Date DATE
TimeOnlyTypeHandler java.util.Date TIME
SqlTimestampTypeHandler java.sql.Timestamp TIMESTAMP
SqlDateTypeHandler java.sql.Date DATE
SqlTimeTypeHandler java.sql.Time TIME
ObjectTypeHandler Any OTHER unseeded type
EnumTypeHandler Enumeration Type VARCHAR - any compatible string type that stores the name of the enumeration (not the index)
EnumOrdinalTypeHandler Enumeration Type Any compatible NUMERIC DOUBLE stores enumered indexes instead of names.

You can override the type processor or create your own type processor to handle unsupported or non-standard types. T his can be done org.apache.ibatis.type.TypeHandler interface, or org.apache.ibatis.type.BaseTypeHandler and then selectively mapping it to a JDBC type. Like what:

    // ExampleTypeHandler.java
    @MappedJdbcTypes(JdbcType.VARCHAR)
    public class ExampleTypeHandler extends BaseTypeHandler {

      @Override
      public void setNonNullParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
        ps.setString(i, parameter);
      }

      @Override
      public String getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return rs.getString(columnName);
      }

      @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);
      }
    }
<!-- mybatis-config.xml -->
<typeHandlers>
  <typeHandler handler="org.mybatis.example.ExampleTypeHandler"/>
</typeHandlers>

Using this type processor overrides the type processor that already exists that handles the String type properties of Java and the VARCHAR parameters and results. N ote that MyBatis does not spy on database metadata to determine which type to use, so you must indicate in the parameters and results map that it is a field of the VARCHAR type 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.

With the generics of a type processor, MyBatis can know the Java type that the type processor handles, but this behavior can be changed in two ways:

  • Add a javaType property (e.g., javaType="String" to the configuration element of the type processor ( typeHandler element);
  • Add an @MappedTypes annotation to @MappedTypes to specify a list of Java types associated with it. If it is also specified in the javaType property, the annotation method is ignored.

There are two ways to specify the type of JDBC that is associated:

  • Add a javaType property to the configuration element of the type processor (e.g., javaType="VARCHAR"
  • Add a @MappedJdbcTypes annotation @MappedJdbcTypes to specify the list of JDBC types associated with it. If it is also specified in the javaType property, the annotation method is ignored.

Finally, let MyBatis find the type processor for you:

<!-- mybatis-config.xml -->
<typeHandlers>
  <package name="org.mybatis.example"/>
</typeHandlers>

Note That when using autodiscovery, the type of JDBC can only be specified by annotation.

You can create a generic type processor that can handle more than one class. To do this, you need to add a constructor that receives the class as an argument so that MyBatis will pass in a specific class when constructing a type processor.

    //GenericTypeHandler.java
    public class GenericTypeHandler extends BaseTypeHandler {

      private Class type;

      public GenericTypeHandler(Class type) {
        if (type == null) throw new IllegalArgumentException("Type argument cannot be null");
        this.type = type;
      }
      ...

EnumTypeHandler EnumOrdinalTypeHandler are both generic type processors, which we'll explore in more detail in the next section.

The enumerity type is processed

To map Enum you need to choose one from EnumTypeHandler or EnumOrdinalTypeHandler to use.

Let's say we want to store rounding patterns that are used when taking approximations. By default, MyBatis uses EnumTypeHandler convert Enum to their corresponding names.

Note EnumTypeHandler in a sense special, with other processors targeting only a particular class, and it's different in that it handles Enum

However, we may not want to store names, but instead our DBAs insist on using plastic value code. It's just as easy: EnumOrdinalTypeHandler typeHandlers so that RoundingMode to the corresponding shaping by their sequentium values.

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

But how can the same Enum mapped to both strings and shaping?

Auto-mapper automatically uses EnumOrdinalTypeHandler so if we want to use EnumTypeHandler we don't have to explicitly set the type processor to use for those SQL statements.

(The next section doesn't start talking about mapping files until the next section, so if you're reading the document for the first time, you might want to go through this step and look at it later.)

<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.apache.ibatis.submitted.rounding.Mapper">
    <resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="funkyNumber" property="funkyNumber"/>
        <result column="roundingMode" property="roundingMode"/>
    </resultMap>

    <select id="getUser" resultMap="usermap">
        select * from users
    </select>
    <insert id="insert">
        insert into users (id, name, funkyNumber, roundingMode) values (
            #{id}, #{name}, #{funkyNumber}, #{roundingMode}
        )
    </insert>

    <resultMap type="org.apache.ibatis.submitted.rounding.User" id="usermap2">
        <id column="id" property="id"/>
        <result column="name" property="name"/>
        <result column="funkyNumber" property="funkyNumber"/>
        <result column="roundingMode" property="roundingMode" typeHandler="org.apache.ibatis.type.EnumTypeHandler"/>
    </resultMap>
    <select id="getUser2" resultMap="usermap2">
        select * from users2
    </select>
    <insert id="insert2">
        insert into users2 (id, name, funkyNumber, roundingMode) values (
            #{id}, #{name}, #{funkyNumber}, #{roundingMode, typeHandler=org.apache.ibatis.type.EnumTypeHandler}
        )
    </insert>

</mapper>

Note that the select statement here enforces resultMap instead resultType

Object Factory

Each time MyBatis creates a new instance of a result object, it uses an ObjectFactory instance to complete it. A ll the default object factory needs to do is instantiate the target class, either by the default construction method or by the parameter construct method when the parameter map exists. I f you want to override the default behavior of an object factory, you can do so by creating your own object factory. Like what:

    // ExampleObjectFactory.java
    public class ExampleObjectFactory extends DefaultObjectFactory {
      public Object create(Class type) {
        return super.create(type);
      }
      public Object create(Class type, List constructorArgTypes, List constructorArgs) {
        return super.create(type, constructorArgTypes, constructorArgs);
      }
      public void setProperties(Properties properties) {
        super.setProperties(properties);
      }
      public  boolean isCollection(Class type) {
        return Collection.class.isAssignableFrom(type);
      }}
<!-- mybatis-config.xml -->
<objectFactory type="org.mybatis.example.ExampleObjectFactory">
  <property name="someProperty" value="100"/>
</objectFactory>

The ObjectFactory interface is simple and contains two methods for creation, one for handling the default construction method and the other for the construction method with parameters. Finally, the setProperties method can be used to configure ObjectFactory, and after initializing your ObjectFactory instance, the properties defined in the objectFactory element body are passed to the setProperties method.

Plugins

MyBatis allows you to intercept calls at some point during the execution of a mapped statement. By default, MyBatis allows method calls intercepted using plug-ins to include:

  • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  • ParameterHandler (getParameterObject, setParameters)
  • ResultSetHandler (handleResultSets, handleOutputParameters)
  • StatementHandler (prepare, parameterize, batch, update, query)

Details of the methods in these classes can be found by looking at the signatures of each method, or by looking directly at the source code in MyBatis' distribution package. A ssuming that you want to do more than just monitor the call to a method, you should have a good understanding of the behavior of the method being rewritten. B ecause if you're trying to modify or rewrite the behavior of an existing method, you're probably breaking myBatis's core module. These are lower-level classes and methods, so be especially careful when using plug-ins.

With the powerful mechanisms provided by MyBatis, it's easy to use plug-ins, simply implement the Interceptor interface and specify the method signature you want to block.

    // ExamplePlugin.java
    @Intercepts({@Signature(
      type= Executor.class,
      method = "update",
      args = {MappedStatement.class,Object.class})})
    public class ExamplePlugin implements Interceptor {
      public Object intercept(Invocation invocation) throws Throwable {
        return invocation.proceed();
      }
      public Object plugin(Object target) {
        return Plugin.wrap(target, this);
      }
      public void setProperties(Properties properties) {
      }
    }
<!-- mybatis-config.xml -->
<plugins>
  <plugin interceptor="org.mybatis.example.ExamplePlugin">
    <property name="someProperty" value="100"/>
  </plugin>
</plugins> 

The plug-in above blocks all "update" method calls in the Executor instance, where Executor is the internal object responsible for executing low-level mapping statements.

NOTE overrides the configuration class

In addition to modifying myBatis core behavior with plug-ins, you can do this by completely overwriting the configuration class. S imply inherit and overwrite each of these methods and pass it to the sqlSessionFactoryBuilder.build (myConfig) method. Again, this could seriously affect MyBatis' behavior, so be careful.

Configure the environment

MyBatis can be configured to accommodate multiple environments, a mechanism that helps to apply SQL mapping to multiple databases for a variety of reasons. F or example, a development, test, and production environment requires different configurations, or multiple production databases that share the same Schema and want to use the same SQL mapping. Many similar use cases.

Keep in mind, however, that although multiple environments can be configured, each SqlSessionFactory instance can only select one of them.

So if you want to connect two databases, you need to create two SqlSesionFactory instances, one for each database. And if it's three databases, you need three instances, and so on, it's easy to remember:

  • Each database corresponds to one instance of SqlSessionFactory

To specify which environment to create, simply pass it as an optional parameter to sqlSessionFactoryBuilder. The two method signatures that can accept environment configuration are:

    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment);
    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader, environment,properties);

If the environment parameters are ignored, the default environment will be loaded as follows:

    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader);
    SqlSessionFactory factory = sqlSessionFactoryBuilder.build(reader,properties);

Environment elements define how the environment is configured.

<environments default="development">
  <environment id="development">
    <transactionManager type="JDBC">
      <property name="..." value="..."/>
    </transactionManager>
    <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>

Note the key points here:

  • The default environment ID (e.g., default="development").
  • The environment ID defined by each environment element (e.g., id="development").
  • Configuration of the transaction manager (e.g., type"JDBC").
  • Configuration of the data source (e.g., type -"POOLED").

The default environment and environment ID is at a glance. As soon as you name it, just make sure that the default environment matches one of the environment IDs.

Transaction Manager

There are two types of transaction managers in MyBatis (i.e., type""|" MANAGED]"):

  • JDBC - This configuration uses the commit and rollback settings of JDBC directly, which relies on the connections obtained from the data source to manage the transaction scope.
  • MANAGED - This configuration does almost nothing. I t never commits or rolls back a connection, but lets the container manage the entire lifecycle of the transaction, such as the context of the JEE application server. I t shuts down the connection by default, but some containers don't want it, so you need to set the closeConnection property to false to prevent it from closing by default. For example:
<transactionManager type="MANAGED">
  <property name="closeConnection" value="false"/>
</transactionManager>

NOTE If you're using Spring and MyBatis, there's no need to configure The Transaction Manager, because the Spring module uses its own manager to override the previous configuration.

Neither transaction manager type requires any properties. They are nothing more than type aliases, in other words, you can replace them with fully qualified or type aliases for the implementation class of the TransactionFactory interface.

    public interface TransactionFactory {
      void setProperties(Properties props);
      Transaction newTransaction(Connection conn);
      Transaction newTransaction(DataSource dataSource, TransactionIsolationLevel level, boolean autoCommit);
    }

Any properties configured in XML will be passed to the setProperties() method after instantiation. You also need to create an implementation class for the Transaction interface, which is also simple:

    public interface Transaction {
      Connection getConnection() throws SQLException;
      void commit() throws SQLException;
      void rollback() throws SQLException;
      void close() throws SQLException;
    }

Using these two interfaces, you can fully customize MyBatis' handling of transactions.

DataSource

The dataSource element uses the standard JDBC data source interface to configure the resources of the JDBC connection object.

  • Many MyBatis applications will configure the data source as shown in the example. H owever, it is not necessary. Be aware that data sources are required to facilitate the use of lazy loading.

There are three built-in data source types (i.e., type" (UNPOOLED| P OOLED| JNDI]"):

UNPOOLED - The implementation of this data source is simply to open and close the connection each time it is requested. A lthough a little slow, it's a good choice for simple applications that don't have performance requirements for timely available connections. D ifferent databases behave differently in this regard, so it is not important for some databases to use a connection pool, and this configuration is ideal. UnPOOLED-type data sources only need to configure the following 5 properties:

  • driver - This is the fully qualified name of the Java class driven by JDBC (not the data source class that might be included in the JDBC driver).
  • url - This is the JDBC URL address of the database.
  • username user name that logs on to the database.
  • password the password to log on to the database.
  • defaultTransactionIsolationLevel the default level of connection transaction isolation.

As an option, you can also pass properties to the database driver. To do this, the property is prefixed with "driver.", for example:

  • driver.encoding=UTF8

This will pass the encoding property with a value of UTF8 to the database driver via the DriveManager.getConnection (url, driverProperties) method.

POOLED - This implementation of this data source leverages the concept of a "pool" to organize JDBC connection objects, avoiding the initialization and authentication times necessary to create new connection instances. This is a popular way for a compliable web app to respond quickly to requests.

In addition to the properties mentioned above under UNPOOLED, there are more properties to configure poolED's data sources:

  • poolMaximumActiveConnections active (i.e. in use) connections that can exist at any time, default: 10
  • poolMaximumIdleConnections The number of idle connections that may exist at any time.
  • poolMaximumCheckoutTime - Checked out of pool connection time before being forced back, default: 20,000 milliseconds (i.e. 20 seconds)
  • poolTimeToWait an underlying setting that, if it takes a considerable amount of time to get a connection, prints the status log to the connection pool and tries again to get a connection (avoiding a failure that has been quiet in the event of misconfiguration), with a default value of 20,000 milliseconds (i.e. 20 seconds).
  • poolPingQuery reconnaissance query sent to a database to verify that the connection is in normal working order and ready to accept the request. The default is NO PING QUERY SET, which causes most database drivers to fail with an appropriate error message.
  • poolPingEnabled Whether to enable reconnaissance queries. If turned on, you must also set the poolPingQuery property (preferably a very fast SQL) with an executable SQL statement, the default: false.
  • poolPingConnectionsNotUsedFor - Configure the frequency of use of PoolPingQuery. This can be set to match specific database connection timeouts to avoid unnecessary detection, with a default value of 0 (i.e. all connections are detected at every moment - of course only when PoolPingEnabled is true).

JNDI - This data source is implemented to be used in containers such as EJBs or application servers, which can centrally or externally configure the data source and then place a reference to the JNDI context. This data source configuration requires only two properties:

  • initial_context This property is used to find context in InitialContext (i.e., initialContext.lookup (initial_context). This is an optional property, and if ignored, data_source property will be looked for directly from InitialContext.
  • data_source is the path to the context that refers to the location of the data source instance. Provides initial_context is looked up in the context it returns when configured, and in InitialContext when it is not provided.

Similar to other data source configurations, you can add the prefix "env." P ass the property directly to the initial context. Like what:

  • env.encoding=UTF8

This passes the encoding property with a value of UTF8 to its construction method when the initial context (InitialContext) is encoding

Any third-party data source can also be used by using the interface org.apache.ibatis.datasource.DataSourceFactory which requires an implementation interface:

    public interface DataSourceFactory {
      void setProperties(Properties props);
      DataSource getDataSource();
    }

org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory be used as a parent class to build a new data source adapter, such as the following code necessary to insert a C3P0 data source:

    import org.apache.ibatis.datasource.unpooled.UnpooledDataSourceFactory;
    import com.mchange.v2.c3p0.ComboPooledDataSource;

    public class C3P0DataSourceFactory extends UnpooledDataSourceFactory {

      public C3P0DataSourceFactory() {
        this.dataSource = new ComboPooledDataSource();
      }
    }

To make it work, add a property to each setter method that requires a MyBatis call. Here's an example of connecting to a PostgreSQL database:

<dataSource type="org.myproject.C3P0DataSourceFactory">
  <property name="driver" value="org.postgresql.Driver"/>
  <property name="url" value="jdbc:postgresql:mydb"/>
  <property name="username" value="postgres"/>
  <property name="password" value="root"/>
</dataSource>

databaseIdProvider

MyBatis can execute different statements depending on the database vendor, and this multi-vendor support is based on the databaseId statement. M yBatis loads all statements without databaseId property and with the databaseId the current database databaseId. I f you find the databaseId and without databaseId the latter is discarded. To support multi-vendor features, simply include databaseIdProvider .xml mybatis-config file as below:

<databaseIdProvider type="DB_VENDOR" />

The DB_VENDOR here is set by the string returned by DatabaseMetaData#getDatabaseProductName() Because this string is usually very long and different versions of the same product return different values, it's a good idea to make it shorter by setting a property alias, as follows:

<databaseIdProvider type="DB_VENDOR">
  <property name="SQL Server" value="sqlserver"/>
  <property name="DB2" value="db2"/>        
  <property name="Oracle" value="oracle" />
</databaseIdProvider>

When there are properties, DB_VENDOR databaseIdProvider is set to the value of the first property key that matches the name of the database product, and if there is no matching property, it is set to "null". In this example, getDatabaseProductName() returns Oracle DataDirect, the databaseId will be set to Oracle.

You can build your own DatabaseIdProvider by implementing the interface org.apache.ibatis.mapping.DatabaseIdProvider and .xml in the mybatis-config database:

    public interface DatabaseIdProvider {
      void setProperties(Properties p);
      String getDatabaseId(DataSource dataSource) throws SQLException;
    }

Mappers

Now that myBatis' behavior has been configured by the above elements, we are now defining sql mapping statements. B ut first we need to tell MyBatis where to find these statements. J ava doesn't provide a good way to find it automatically, so the best way is to tell MyBatis where to find the mapping file. Y ou can use resource references relative to class paths, or fully qualify resource file:/// or class names and package names, and so on. For example:

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

These configurations tell MyBatis where to look for mapping files, and the rest of the details should be each SQL mapping file, which is what we'll discuss next.