I am working on a web-application and I need to configure a PoolingDataSource from Apache Commons DBCP in order to support some level of user-concurrency. I tried BasicDataSource but it does not seems to be the solution. The point is that in BasicDataSource I can set some parameters like these bellow:
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUsername("sa");
dataSource.setPassword("");
dataSource.setUrl("jdbc:h2:mem:");
dataSource.setMaxActive(10);
dataSource.setMaxIdle(5);
dataSource.setInitialSize(5);
dataSource.setValidationQuery("SELECT 1");
And it will initialize 5 Connections and keep them in the pool and do its thing. I can also get some statistics using a BasicDataSource like NumActiveConnections and NumIdleConnections. Now, with a PoolingDataSource, how do I set these values properties to the DataSources? and how can I get some connection statistics from the pool?
And one last question, in order to consume a connection, should I setup a DataSource each time I need Connection or should I setup a unique DataSource in a static variable and create all Connections from there? How should I manage the DataSoures and Connections?
I currently setup the DataSources using the following code:
public static DataSource setupDataSource(String connectURI) {
ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(connectURI,null);
PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory, null);
ObjectPool<PoolableConnection> connectionPool = new GenericObjectPool<>(poolableConnectionFactory);
poolableConnectionFactory.setPool(connectionPool);
PoolingDataSource<PoolableConnection> dataSource = new PoolingDataSource<>(connectionPool);
return dataSource;
}
Related
I want to create a one-shot database connection, based on spring classes.
To prevent spring loading the datasource on startup, I create it explicit when needed (only occasionally). I don't need any connection pooling, transactions and stuff like that.
DriverManagerDataSource ds = new DriverManagerDataSource(props.getUrl(), props.getUsername(), props.getPassword());
JdbcTemplate jdbc = new JdbcTemplate(ds);
jdbc.execute(...);
Question: how can I afterwards close/destroy the datasource and any open connections explicit?
Using application.properties we can provide the
spring.datasource.hikari.maximum-pool-size=10
as spring using the Hikari connection pooling by default.
But when we are creating datasource manually as a specific requirement we cannot use the application.properties.
Scenario.
User will configure the datasource dynamically and that connection object should be available from thereafter.
For this we are creating DatasourceBuilder.create().build() method to create a datasource connection object and set it into the bean factory.
But while creating a datasource connection object using DataSourceBuilder.create().build() method it is creating connection pooling and 10 connection to the database at the same time.
We wanted to avoid that connection pooing and have only one connection.
How do I do that?
While creating the custom datasource we can create an instance of HikariDataSource instead of DataSource.
Assuming you are using Spring default Connection pooling (Hikari)
public DataSource createCustomConnection(String driverClass, String url, String username, String password) {
HikariConfig config = new HikariConfig();
config.setDriverClassName(driverClass);
config.setJdbcUrl(url);
config.setUsername(username);
config.setPassword(password);
config.setMaximumPoolSize(MENTIONED_TOTAL_CONNECTIONS);
// Like this you can configure multiple properties here
HikariDataSource dataSource = new HikariDataSource(config);
return dataSource;
}
DataSource dataSource = createCustomConnection(...) // Pass Parameters here
Here you have created the datasource that creates a single connection at the same time.
for more information https://github.com/brettwooldridge/HikariCP#initialization
Thank you.
You can try setting the minimumIdle property. By default it is set to maxPoolSize, so 10 connections are created initially. You can refer minimumIdle section in this link, https://github.com/brettwooldridge/HikariCP#frequently-used
I'm trying to set up pooling with SQLServerDataSource if i understand this answer
https://stackoverflow.com/a/25573035/1262568
public DataSource dataSource() {
DataSourceBuilder factory = DataSourceBuilder
.create(this.properties.getClassLoader())
.driverClassName(this.properties.getDriverClassName())
.url(this.properties.getUrl())
.username(this.properties.getUsername())
.password(this.properties.getPassword());
return factory.build();
}
Geting connection from a DataSource created in that way will return pooled connection using one of the available connection pools.
But what if instead DataSourceBuilder i want to use SQLServerDataSource
Will it also automatically use one of the available connection pool?
public DataSource dataSource() {
SQLServerDataSource sqlServerDataSource = new SQLServerDataSource();
sqlServerDataSource.setUser(UserName);
sqlServerDataSource.setPassword(Password);
sqlServerDataSource.setURL(Url);
return sqlServerDataSource;
}
Will it also automatically use one of the available connection pool?
No it won't. SQLServerDataSource is a SQL Server (driver) specific class, whereas DataSourceBuilder is a Spring class. Only the latter knows about Spring and its configuration and its configured connection pool.
Is there a reason you'd need to use SQLServerDataSource?
To access the native connection even from the pool, use
SQLServerConnection conn = connection.unwrap(SQLServerConnection.class);
just remember to call close() on connection and not conn, so the connection can be returned to the pool.
MysqlDataSource source = new MysqlDataSource();
source.setURL(properties.getString("url"));
source.setUser(properties.getString("user"));
source.setPassword(properties.getString("password"));
How do set quantity of min and max connections in pool connection ?
Like here
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUsername("username");
dataSource.setPassword("password");
dataSource.setUrl("jdbc:mysql://<host>:<port>/<database>");
dataSource.setMaxActive(10);
dataSource.setMaxIdle(5);
dataSource.setInitialSize(5);
The class com.mysql.jdbc.jdbc2.optional.MysqlDataSource is a simple javax.sql.DataSource implementation that only serves as a simple factory for connections, it does not provide connection pooling.
The MySQL Connector/J driver does not provide any data source that provides connection pooling. Judging by the name, you might think MysqlConnectionPoolDataSource is one, but it is only a factory for use by a connection pool, it isn't a connection pool itself.
If you want a connection pool, use a connection pool library like Apache DBCP (which provides that BasicDataSource in your second example), HikariCP, or c3p0.
You'll have to put it in connection string: "jdbc:mysql://localhost:3306/test?max-connections=100..."
To specify SQLite connection properties there is org.sqlite.SQLiteConfig and it goes something like this:
org.sqlite.SQLiteConfig config = new org.sqlite.SQLiteConfig();
config.setReadOnly(true);
config.setPageSize(4096); //in bytes
config.setCacheSize(2000); //number of pages
config.setSynchronous(SQLiteConfig.SynchronousMode.OFF);
config.setJournalMode(SQLiteConfig.JournalMode.OFF);
SQLiteConnectionPoolDataSource dataSource = new SQLiteConnectionPoolDataSource();
Creating a connection pool with c3p0 goes something like this:
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass("org.sqlite.JDBC");
cpds.setJdbcUrl("jdbc:sqlite:/foo/bar");
cpds.setMaxPoolSize(10);
Question: how do I create a DataSource that combines the two, letting me set things like the connection pool's max-pool-size and sqlite's synchronous mode?
Try
//put the imports where they really go, obviously...
import javax.sql.*;
import org.sqlite.*;
import com.mchange.v2.c3p0.*;
// configure SQLite
SQLiteConfig config = new org.sqlite.SQLiteConfig();
config.setReadOnly(true);
config.setPageSize(4096); //in bytes
config.setCacheSize(2000); //number of pages
config.setSynchronous(SQLiteConfig.SynchronousMode.OFF);
config.setJournalMode(SQLiteConfig.JournalMode.OFF);
// get an unpooled SQLite DataSource with the desired configuration
SQLiteDataSource unpooled = new SQLiteDataSource( config );
// get a pooled c3p0 DataSource that wraps the unpooled SQLite DataSource
DataSource pooled = DataSources.pooledDataSource( unpooled );
The DataSource pooled will now be a c3p0 PooledDataSource that wraps an SQLite unpooled DataSource which has been configured as you wish.
Please see c3p0's docs, "Using the DataSources factory class", and the API docs for the DataSources factory class.
See also the javadocs for SQLite JDBC, which I downloaded from here to answer this question.