DsFactory

Interpretation

The concept of DataSource comes from the JDBC specification. A DataSource represents a description of a database (or cluster), from which we can obtain N database connections to perform operations on the database.

Each open-source JDBC connection pool has an implementation of DataSource, such as DruidDataSource for Druid and HikariDataSource for Hikari. However, the configuration of each connection pool varies, and the configuration files are different. Hutool encapsulates commonly used connection pools to simplify and provide consistent configuration to the maximum extent.

Hutool’s solution is to use a single configuration file config/db.setting in the ClassPath to configure data sources for all types of connection pools, and then use the DsFactory.get() method to automatically identify the data source and inject the connection pool configuration (including the database connection configuration) in the configuration file. DsFactory automatically builds the corresponding data source by detecting the jar packages introduced in the project in order using try to identify which connection pool the user is using.

Hutool supports the following connection pools and detects their existence in order:

  1. HikariCP
  2. Druid
  3. Tomcat
  4. Dbcp
  5. C3p0

In the absence of any introduced connection pool, Hutool will use its built-in connection pool: Hutool Pooled (a simple connection pool, not recommended for use in production environments).

Basic Usage

1. Introduce the jar of the connection pool

Hutool does not strongly depend on any third-party libraries. Within the scope of Hutool-supported connection pools, users need to choose their preferred connection pool and introduce it themselves.

2. Write the configuration file

In a Maven project, create the file db.setting under src/main/resources/config and write the configuration file. This configuration file location is a convention between Hutool and the user (in line with the principle of “convention over configuration”):

The configuration file is divided into two parts:

1. Basic connection information

## Basic configuration information
# JDBC URL, use the corresponding JDBC connection string for different databases
url = jdbc:mysql://<host>:<port>/<database_name>
# Username, you can also use user here
username = username
# Password, you can also use pass here
password = password
# JDBC driver name, optional (Hutool will automatically recognize it)
driver = com.mysql.jdbc.Driver

Tip The driver is optional, and Hutool will automatically load the corresponding Driver class based on the url. The basic connection information is common to all connection pools, and in principle, only the basic information is needed to successfully connect and operate the database.

2. Connection pool-specific configuration information

The configuration information specific to different connection pools varies in addition to the basic information, and Hutool encapsulates their configuration items for different connection pools. You can see the sample configuration files for different connection pools in the src/test/resources/example directory of the project. Let’s take HikariCP as an example:

# Auto-commit
autoCommit = true
# The maximum time (in milliseconds) to wait for a connection from the connection pool to be allocated. If no available connection is available within this time, a SQLException will occur. Default: 30 seconds.
connectionTimeout = 30000
# The maximum idle time (in milliseconds) of a connection. If a connection is idle for more than this time, it will be released (retired). Default: 10 minutes.
idleTimeout = 600000
# The lifetime (in milliseconds) of a connection. If a connection is not used and exceeds this time, it will be released (retired). Default: 30 minutes. It is recommended to set it 30 seconds less than the database timeout to ensure safety. Reference MySQL wait_timeout parameter (show variables like '%timeout%';) 
maxLifetime = 1800000
# The test SQL to be executed before getting a connection. 
connectionTestQuery = SELECT 1
# The minimum number of idle connections. 
minimumIdle = 10; 
# The maximum number of connections allowed in the connection pool. Default value: 10; recommended formula: ((core_count * 2) + effective_spindle_count) 
maximumPoolSize = 10; 
# Set to true when connecting to a read-only database to ensure security
readOnly = false

3. Obtaining a Data Source

//Obtain the default data source
DataSource ds = DSFactory.get();

Yes, it’s that simple. A single method can identify the data source and read the information from the default path (config/db.setting) to obtain the data source.

4. Directly Creating a Data Source

Of course, you can still obtain a data source object according to the method of the connection pool itself. Let’s take Druid as an example:

//Please refer to the Druid official documentation for specific configuration parameters
DruidDataSource ds2 = new DruidDataSource();
ds2.setUrl("jdbc:mysql://localhost:3306/dbName");
ds2.setUsername("root");
ds2.setPassword("123456");

5. Creating a Simple Data Source

Sometimes our operation is very simple, or we just want to test whether the remote database is accessible. We can use the SimpleDataSource provided by Hutool:

DataSource ds = new SimpleDataSource("jdbc:mysql://localhost:3306/dbName", "root", "123456");

SimpleDataSource is just a simple packaging of DriverManager.getConnection and does not support pooling functionality. It is particularly suitable for operations with a small number of database connections. Similarly, SimpleDataSource also supports the default configuration file:

DataSource ds = new SimpleDataSource();

Advanced Usage

1. Customizing the Connection Pool

Sometimes, when a project introduces multiple data sources, we may want to customize the required connection pool. In this case, we can do the following:

//Set the custom connection pool implementation as Tomcat-pool
DSFactory.setCurrentDSFactory(new TomcatDSFactory());
DataSource ds = DSFactory.get();

It should be noted that DSFactory.setCurrentDSFactory is a global method that must be called before all opportunities to obtain a data source, and it only needs to be called once (for example, at project startup).

2. Customizing the Configuration File

Sometimes, due to project planning issues, we may want to customize the location of the database configuration Setting, or even dynamically load the Setting object. In this case, we can use the following method to obtain the database connection information from another Setting object:

//Custom database Setting, for more usage, please refer to the Hutool-Setting chapter
Setting setting = new Setting("otherPath/other.setting");
//Obtain the specified configuration, the second parameter is the group for multiple data sources, pass null if there is no group
//Note that DSFactory needs to be reused or closed here
DataSource ds = DSFactory.create(setting).getDataSource();

3. Multiple Data Sources

Sometimes we need to operate different databases, or we may need to operate different databases for production, development, and testing environments. Regardless of the situation, Hutool provides excellent support for multiple data sources. There are two ways to implement multiple data sources:

1. Obtain data sources from multiple configuration files respectively By reading multiple configuration files in the same way as customizing the configuration file.

2. Isolate different data source configurations in the same configuration file using groups:

[group_db1] 
url = jdbc:mysql://<host>:<port>/<database_name> 
username = username 
password = password 
[group_db2] url = jdbc:mysql://<host2>:<port>/<database_name> 
username = username 
password = password 

We write the db.setting file in the above way, and then:

DataSource ds1 = DSFactory.get("group_db1");
DataSource ds2 = DSFactory.get("group_db2"); 

In this way, we can implement multiple data source configurations in a single configuration file.

Conclusion

Hutool provides various ways to obtain DataSource objects, which can be used not only within Hutool itself but also passed to different frameworks for seamless integration.

Hutool’s encapsulation of data sources well illustrates the following principles:

  1. automatic recognition is preferred to user definition,
  2. convenience and flexibility coexist, and
  3. adaptability and compatibility.