Detailed description of <environments> configuration elements for Mybatis configuration

In this article, we continue to look at other configuration elements. Today's protagonist is our <environments> element, which is used to set up the database configuration we need to access. Let's first look at the configuration:

<environments default="development">
		<environment id="development">
			<!-- Use jdbc transaction management -->
			<transactionManager type="JDBC" />
			<!-- Database connection pool -->
			<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>

From the above point of view, we know that < environment > can be configured with multiple < environment > element nodes under < environment >, and each < environment > node can be configured with two things, one is transaction manager configuration < transaction Manager > and the other is data source configuration < dataSource >.


Let's start with the source code, see how this piece is parsed, and then see what parameters are configurable inside.

Or starting from the entrance of the analysis:

Inside the method:

From the code point of view, the default attribute of the < environment > tag element is obtained first. The function of this attribute is to specify which database configuration is used in the current situation, that is, which < environment > node configuration is used, and the default value is the id value of the < environment > tag element.

Just like the isSpecifiedEnvironment(id) method in the code above, when traversing all <environment>, it determines whether the corresponding ID is a default value at one time, and if so, initializes the database connection using the current <environment> element.

The isSpecifiedEnvironment method is as follows:

Next, the following code constructs the corresponding object with the set transaction manager and data source.

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());

We start with the parsing of the transaction manager and go into the transactionManagerElement() method:

private TransactionFactory transactionManagerElement(XNode context) throws Exception {
    if (context != null) {
      String type = context.getStringAttribute("type");
      Properties props = context.getChildrenAsProperties();
      TransactionFactory factory = (TransactionFactory) resolveClass(type).newInstance();
      factory.setProperties(props);
      return factory;
    }
    throw new BuilderException("Environment declaration requires a TransactionFactory.");
  }

We can see that the transaction manager is actually found here based on the type attribute of the element <transactionManager>.

Two configurations are supported in Mobile: JDBC and MANAGED. Here, the corresponding transaction manager is returned according to the set value of type. Let's see that in the Configuration class of Meybatis, some association has been made between the two configurations and the corresponding transaction manager, as follows:

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);
  }

The difference between the two transaction managers is:

JDBC: This configuration uses JDBC's commit and rollback settings directly. It relies on connections from data sources to manage transaction scopes.

MANAGED: This configuration does little. It 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). By default, it closes the connection, but some containers don't want to, so you need to set the closeConnection property to false to prevent its default closing behavior. For example:

<transactionManager type="MANAGED">
  <property name="closeConnection" value="false"/>
</transactionManager>

Note: If you are using Spring + MyBatis, there is no need to configure the transaction manager, because the Spring module will use its own manager to override the previous configuration.


Having finished the transaction manager, let's take a look at the data source configuration.

The dataSource element uses the standard JDBC data source interface to configure the resources of JDBC connection objects. Mybatis supports three built-in data source types: UNPOOLED, POOLED, and JNDI. That is, when we configure the type attribute of the < dataSource > element, we can directly support setting these three values.

Here is a brief description of the three types:

(1)UNPOOLED

The implementation of this data source is to open and close the connection each time it is requested. Although a little slow, it's a good choice for simple applications that don't have performance requirements for timely usable connections. Different databases behave differently in this respect, so it is not important to use connection pools for some databases, and this configuration is ideal.

Data sources of UNPOOLED type only need to configure the following five attributes:

Driver: This is the fully qualified name of the Java class driven by JDBC (not the data source class that may be included in the JDBC driver).

url: This is the JDBC URL address of the database.

username: username to log in to the database.

Password: The password to log in to the database.

DefaultTransaction Isolation Level: The default connection transaction isolation level.

As an option, you can also pass properties to the database driver. To do this, the prefix of the attribute is "driver." For example:

driver.encoding=UTF8

This will pass the encoding attribute with UTF8 value to the database driver through the DriverManager.getConnection(url,driverProperties) method.

(2)POOLED

The implementation of this data source uses the concept of "pool" to organize JDBC connection objects, avoiding the necessary initialization and authentication time when creating new connection instances. This is a popular way to make concurrent Web applications respond quickly to requests.

In addition to the attributes mentioned above under UNPOOLED, more attributes will be used to configure POOLED data sources:

Pool Maximum Active Connections: Number of connections that can exist at any time (i.e. in use), default value: 10

Pool Maximum Idle Connections: Number of free connections that may exist at any time.

Pool Maximum Checkout Time: checked out time for pool connections before forced return, default value: 20,000 milliseconds (i.e. 20 seconds)

poolTimeToWait: This is an underlying setting. If it takes a long time to get a connection, it prints the status log to the connection pool and retries a connection (to avoid silent failure in case of misconfiguration). The default value is 20,000 milliseconds (i.e. 20 seconds).

poolPingQuery: A detection query sent to the database to verify that the connection is in 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.

PoolPing Enabled: Enables detection queries. If enabled, you must also set the poolPingQuery property (preferably a very fast SQL) with an executable SQL statement, default value: false. Pool Ping Connections Not Used For: Configure the frequency of use of pool Ping Query. This can be set to match specific database connection timeouts to avoid unnecessary detection, default value: 0 (that is, all connections are detected at every moment) Of course, only if the pool Ping Enabled is true.

(3)JNDI

This data source is implemented to be used in containers such as EJB or application server, which can centralize or configure data sources externally, and then place a reference to the JNDI context. This data source configuration requires only two attributes:

Initial_context: This property is used to find context in InitialContext (that is, initial_context). This is an optional attribute, and if ignored, the data_source attribute will be found directly from the Initial Context.

data_source: This is the path to refer to the context of the location of the data source instance. When the initial_context configuration is provided, it is looked up in the context it returns, and when it is not provided, it is looked up directly in the Initial Context.

Similar to other data source configurations, attributes can be passed directly to the initial context by adding the prefix "env.". For example:

env.encoding=UTF8

This passes an encoding attribute with a value of UTF8 to its constructor when the Initial Context is instantiated.

So far, the configuration and usage of the < environments > elements have been introduced.


If you want to know my latest blog, please pay attention to my blog, thank you. If you want to see more related technical articles and would like to support me to continue writing, please give me a reward. Thank you for your reward.

Keywords: Database JDBC Attribute encoding

Added by phpforme on Tue, 02 Jul 2019 00:03:05 +0300