Set SQLite connection properties in c3p0 connection pool - java

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.

Related

How to properly close a JdbcTemplate DataSource connection?

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?

Set maxConnectionLimit to Manually created connection using Spring DataSourceBuilder.create()

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

MySQL Poolconnection

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..."

How to manage database connection pool in spring jpa?

I am using spring-boot in my web application and use spring-jpa to read/write from/to my database. It works very well but I want to understand how to manage the database connections. Below is my properties configuration for database:
spring.datasource.url=jdbc:mysql://localhost:3306/test?characterEncoding=utf8
spring.datasource.username=user
spring.datasource.password=pwd
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.max-active=500
I have set the maximum connections to 500. When a user makes a request on my spring application, a database connection will be opened for him. After finishing the request, will spring jpa close this connection? If not, when will it close the unused connections?
I have read through the spring jpa reference document from http://docs.spring.io/spring-data/jpa/docs/current/reference/html/. But it doesn't mention anything about the connections.
When using DB connection pooling, a call to sqlconnection.close() will not necessarily close the heavyweight connection to the database, instead most often will just release the connection as re-usable in the pool. That's why it is advisable to invoke the close() on connection as soon as possible when leveraging a client side connection pool.
In your configuration, the pool will contain a maximum number of 500 connections ( it would be also good to configure maxIdle, minIdle, and minEvictableIdleTimeMillis to tune the number of ready-to-use connections and how often to release them when not used).
Some more doc here
You have already found that you can configure this from application.properties
You can find all the possible properties here.
Notice that from Spring Boot 1.4 there are datasource properties for every datasource vendor that spring integrates with, out of the box. There is spring.datasource.dbcp.*,spring.datasource.tomcat.* and so on. See 1.4 docs
If that's not enought, and you need something very specific, you can declare the datasource bean yourself. Here is the example with Tomcat datasource:
#Bean
public DataSource dataSource(){
PoolProperties p = new PoolProperties();
p.setUrl("jdbc:mysql://localhost:3306/mysql");
p.setDriverClassName("com.mysql.jdbc.Driver");
p.setUsername("root");
p.setPassword("password");
p.setJmxEnabled(true);
p.setTestWhileIdle(false);
p.setTestOnBorrow(true);
p.setValidationQuery("SELECT 1");
p.setTestOnReturn(false);
p.setValidationInterval(30000);
p.setTimeBetweenEvictionRunsMillis(30000);
p.setMaxActive(100);
p.setInitialSize(10);
p.setMaxWait(10000);
p.setRemoveAbandonedTimeout(60);
p.setMinEvictableIdleTimeMillis(30000);
p.setMinIdle(10);
p.setLogAbandoned(true);
p.setRemoveAbandoned(true);
p.setJdbcInterceptors(
"org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
"org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
DataSource datasource = new DataSource();
datasource.setPoolProperties(p);
return datasource ;
}

How do I manually configure a DataSource in Java?

I'm trying to follow Sun's JDBC tutorial at http://java.sun.com/docs/books/tutorial/jdbc/basics/connecting.html
It gives the following example code:
DataSource ds = (DataSource) org.apache.derby.jdbc.ClientDataSource()
ds.setPort(1527);
ds.setHost("localhost");
ds.setUser("APP")
ds.setPassword("APP");
Connection con = ds.getConnection();
This code doesn't compile because the DataSource interface has none of these methods, except for the getConnection() method invoked last.
(Here's the javadoc: http://java.sun.com/javase/6/docs/api/javax/sql/DataSource.html)
What am I missing?
Edit:
I'm actually trying to connect to MySQL (com.mysql.jdbc) and I can't find the javadoc for that. I'll accept an answer that points me to either:
1) documentation for com.mysql.jdbc regarding a DataSource that I can understand, or
2) gives an example to follow for what the tutorial's code should be, for any database.
One thing you might want to look at is the Commons DBCP project. It provides a BasicDataSource that is configured fairly similarly to your example. To use that you need the database vendor's JDBC JAR in your classpath and you have to specify the vendor's driver class name and the database URL in the proper format.
Edit:
If you want to configure a BasicDataSource for MySQL, you would do something like this:
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);
dataSource.setValidationQuery("SELECT 1");
Code that needs a DataSource can then use that.
DataSource is vendor-specific, for MySql you could use MysqlDataSource which is provided in the MySql Java connector jar:
MysqlDataSource dataSource = new MysqlDataSource();
dataSource.setDatabaseName("xyz");
dataSource.setUser("xyz");
dataSource.setPassword("xyz");
dataSource.setServerName("xyz.yourdomain.com");
Basically in JDBC most of these properties are not configurable in the API like that, rather they depend on implementation. The way JDBC handles this is by allowing the connection URL to be different per vendor.
So what you do is register the driver so that the JDBC system can know what to do with the URL:
DriverManager.registerDriver((Driver) Class.forName("com.mysql.jdbc.Driver").newInstance());
Then you form the URL:
String url = "jdbc:mysql://[host][,failoverhost...][:port]/[database][?propertyName1][=propertyValue1][&propertyName2][=propertyValue2]"
And finally, use it to get a connection:
Connection c = DriverManager.getConnection(url);
In more sophisticated JDBC, you get involved with connection pools and the like, and application servers often have their own way of registering drivers in JNDI and you look up a DataSource from there, and call getConnection on it.
In terms of what properties MySQL supports, see here.
EDIT: One more thought, technically just having a line of code which does Class.forName("com.mysql.jdbc.Driver") should be enough, as the class should have its own static initializer which registers a version, but sometimes a JDBC driver doesn't, so if you aren't sure, there is little harm in registering a second one, it just creates a duplicate object in memeory.
use MYSQL as Example:
1) use database connection pools: for Example: Apache Commons DBCP , also, you need basicDataSource jar package in your classpath
#Bean
public BasicDataSource dataSource() {
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/gene");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
2)use JDBC-based Driver it is usually used if you don't consider connection pool:
#Bean
public DataSource dataSource(){
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUrl("jdbc:mysql://localhost:3306/gene");
ds.setUsername("root");
ds.setPassword("root");
return ds;
}
I think the example is wrong - javax.sql.DataSource doesn't have these properties either. Your DataSource needs to be of the type org.apache.derby.jdbc.ClientDataSource, which should have those properties.
The javadoc for DataSource you refer to is of the wrong package. You should look at javax.sql.DataSource. As you can see this is an interface. The host and port name configuration depends on the implementation, i.e. the JDBC driver you are using.
I have not checked the Derby javadocs but I suppose the code should compile like this:
ClientDataSource ds = org.apache.derby.jdbc.ClientDataSource()
ds.setHost etc....
For postgres, the below works. I actually used it in integ tests. I guess there should be some more consideration for production usage.
PGSimpleDataSource ds = new PGSimpleDataSource() ;
ds.setServerName( "localhost" );
ds.setDatabaseName( "your_db_name_here" );
ds.setUser( "scott" );
ds.setPassword( "tiger" );
The class is bundled in the postgres jdbc driver.
The original stackoverflow post i followed: https://stackoverflow.com/a/45091982/3877642

Categories

Resources