I tried to find the connection pool which allows to get connection by jdbc url but failed. Hikari connection pool doesn't allow do it, the same situation in c3po.
My use case is:
ConnectionPool.getConnection(jdbcUrl);
Does anybody know such connection pool in java world?
A Simple Guide to Connection Pooling in Java
Author - Baeldung
About Author
A Simple Implementation
To better understand the underlying logic of connection pooling, let's
create a simple implementation.
Let's start out with a loosely-coupled design, based on just one
single interface:
public interface ConnectionPool {
Connection getConnection();
boolean releaseConnection(Connection connection);
String getUrl();
String getUser();
String getPassword();
}
The ConnectionPool interface defines the public API of a basic
connection pool.
Now, let's create an implementation, which provides some basic
functionality, including getting and releasing a pooled connection:
public class BasicConnectionPool
implements ConnectionPool {
private String url;
private String user;
private String password;
private List<Connection> connectionPool;
private List<Connection> usedConnections = new ArrayList<>();
private static int INITIAL_POOL_SIZE = 10;
public static BasicConnectionPool create(
String url, String user,
String password) throws SQLException {
List<Connection> pool = new ArrayList<>(INITIAL_POOL_SIZE);
for (int i = 0; i < INITIAL_POOL_SIZE; i++) {
pool.add(createConnection(url, user, password));
}
return new BasicConnectionPool(url, user, password, pool);
}
// standard constructors
#Override
public Connection getConnection() {
Connection connection = connectionPool
.remove(connectionPool.size() - 1);
usedConnections.add(connection);
return connection;
}
#Override
public boolean releaseConnection(Connection connection) {
connectionPool.add(connection);
return usedConnections.remove(connection);
}
private static Connection createConnection(
String url, String user, String password)
throws SQLException {
return DriverManager.getConnection(url, user, password);
}
public int getSize() {
return connectionPool.size() + usedConnections.size();
}
// standard getters
}
Connection pooling is a well-known data access pattern, whose main
purpose is to reduce the overhead involved in performing database
connections and read/write database operations.
In a nutshell, a connection pool is, at the most basic level, a
database connection cache implementation, which can be configured to
suit specific requirements.
In this tutorial, we'll make a quick roundup of a few popular
connection pooling frameworks, and we'll learn how to implement from
scratch our own connection pool.
Why Connection Pooling?
The question is rhetorical, of course.
If we analyze the sequence of steps involved in a typical database
connection life cycle, we'll understand why:
Opening a connection to the database using the database driver Opening
a TCP socket for reading/writing data Reading / writing data over the
socket Closing the connection Closing the socket It becomes evident
that database connections are fairly expensive operations, and as
such, should be reduced to a minimum in every possible use case (in
edge cases, just avoided).
Here's where connection pooling implementations come into play.
By just simply implementing a database connection container, which
allows us to reuse a number of existing connections, we can
effectively save the cost of performing a huge number of expensive
database trips, hence boosting the overall performance of our
database-driven applications.
JDBC Connection Pooling Frameworks
From a pragmatic perspective, implementing a connection pool from the
ground up is just pointless, considering the number of
“enterprise-ready” connection pooling frameworks available out there.
From a didactic one, which is the goal of this article, it's not.
Even so, before we learn how to implement a basic connection pool,
let's first showcase a few popular connection pooling frameworks.
Apache Commons DBCP
public class DBCPDataSource {
private static BasicDataSource ds = new BasicDataSource();
static {
ds.setUrl("jdbc:h2:mem:test");
ds.setUsername("user");
ds.setPassword("password");
ds.setMinIdle(5);
ds.setMaxIdle(10);
ds.setMaxOpenPreparedStatements(100);
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
private DBCPDataSource(){ }
}
In this case, we've used a wrapper class with a static block to easily
configure DBCP's properties.
Here's how to get a pooled connection with the DBCPDataSource class:
connection con = DBCPDataSource.getConnection();
HikariCP
public class HikariCPDataSource {
private static HikariConfig config = new HikariConfig();
private static HikariDataSource ds;
static {
config.setJdbcUrl("jdbc:h2:mem:test");
config.setUsername("user");
config.setPassword("password");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
ds = new HikariDataSource(config);
}
public static Connection getConnection() throws SQLException {
return ds.getConnection();
}
private HikariCPDataSource(){}
}
Similarly, here's how to get a pooled connection with the
HikariCPDataSource class:
Connection con = HikariCPDataSource.getConnection();
Related
I've been using several connection pooling api's before but I thought its time to do something on my own. Iam currently searching for a very basic MySQL Connection Pooling function on which I can build on. I really would appreciate if you guys could give me a honest opinion!
Here's the code:
package temp.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class MySQL {
private static final String driver = "com.mysql.jdbc.Driver";
private static final String url = "jdbc:mysql://localhost:3306/beta";
private static final String username = "root";
private static final String password = "mypassword";
private static List<Connection> pool = new ArrayList<Connection>();
public static void setup() {
try {
for(int i = 0; i < 5; i++) {
Class.forName(driver);
Connection connection = DriverManager.getConnection(url, username, password);
pool.add(connection);
}
}
catch (ClassNotFoundException e) { e.printStackTrace(); }
catch (SQLException e) { e.printStackTrace(); }
}
public static void addConnection(Connection connection) {
pool.add(connection);
}
public static Connection getConnection() {
Connection connection = null;
if(pool.size() <= 0) return connection;
connection = pool.get(0); pool.remove(0);
return connection;
}
}
Thanks in advance!
Sincerely,
Gemaken
There's some major issues with your implementation of a connection pool - connections aren't returned to the pool, no thread-safety, no blocking when all connections are being used, it's static, etc.
Given this, I'll start with the basics.
First, the whole point of any pool is to hold an expensive resource, in this case a javax.sql.Connection, so that it may be reused in the future avoiding the cost of creating that resource again.
With most pools there's a min and max - when created the pool will create the min number of resources and can expand upto the max as the resources are consumed.
When a resource is retrieved from a pool, the retrieving thread should be guaranteed exclusive use of that resource, until the resource is returned to the pool.
Should all resources be being used, any further attempts to obtain a resource should block (with some sort of timeout) until a resource is available.
The use of a pool implies that the application is multi-threaded, so it is also important that the implementation is thread-safe.
As the JDBC API is well defined connection pools typically implement javax.sql.DataSource allowing connection pools to be switched in and out as needed. Given this javax.sql.Connection.close() should be used to return the connection to the pool.
A dba in my office proposed the following to audit db access (oracle):
Put the current logged in user in my application as a property on the db connection (java.sql.Connection).
public class ClientInfoProvider {
void enrichConnection(Connection connection, String userName) throws SQLException {
OracleConnection oConn = (OracleConnection) connection;
String[] metrics = new String[OracleConnection.END_TO_END_STATE_INDEX_MAX];
metrics[OracleConnection.END_TO_END_CLIENTID_INDEX] = userName;
oConn.setEndToEndMetrics(metrics, (short) 0);
}
}
public class AuditableDataSource implements DataSource {
...
#Override
public Connection getConnection() throws SQLException {
Connection connection = dataSource.getConnection();
clientInfoProvider.enrichConnection(connection, loggedInUserString);
return connection;
}
...
}
My main concern is that connections are pooled. Wil users not end up using the same connection? The last user which changes the properties of the connection might influence the other users that are already using this connection. Is this a correct assumption?
Using the Spring jdbc datasource, a jdbc connection lives only long enough to execute it's query. Once the query is executed and the resultset has been closed, the connection will also be closed and released to the pool to be used for another query.
I am new in connection pooling.I have a created a connection pool in mysql that adds five connections.Now i want to know what is the application of connection pooling,i.e after creating that pool how to use that.. i am pasting my code here
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Vector;
import com.mysql.jdbc.Connection;
class ConnectionPoolManager {
String databaseUrl = "jdbc:mysql://localhost:3306/homeland";
String userName = "root";
String password = "root";
Vector connectionPool = new Vector();
public ConnectionPoolManager() {
initialize();
}
public ConnectionPoolManager(
// String databaseName,
String databaseUrl, String userName, String password) {
this.databaseUrl = databaseUrl;
this.userName = userName;
this.password = password;
initialize();
}
private void initialize() {
// Here we can initialize all the information that we need
initializeConnectionPool();
}
private void initializeConnectionPool() {
while (!checkIfConnectionPoolIsFull()) {
System.out
.println("Connection Pool is NOT full. Proceeding with adding new connections");
// Adding new connection instance until the pool is full
connectionPool.addElement(createNewConnectionForPool());
}
System.out.println("Connection Pool is full.");
}
private synchronized boolean checkIfConnectionPoolIsFull() {
final int MAX_POOL_SIZE = 5;
// Check if the pool size
if (connectionPool.size() < 5) {
return false;
}
return true;
}
// Creating a connection
private Connection createNewConnectionForPool() {
Connection connection = null;
try {
Class.forName("com.mysql.jdbc.Driver");
connection = (Connection) DriverManager.getConnection(databaseUrl,
userName, password);
System.out.println("Connection: " + connection);
} catch (SQLException sqle) {
System.err.println("SQLException: " + sqle);
return null;
} catch (ClassNotFoundException cnfe) {
System.err.println("ClassNotFoundException: " + cnfe);
return null;
}
return connection;
}
public synchronized Connection getConnectionFromPool() {
Connection connection = null;
// Check if there is a connection available. There are times when all
// the connections in the pool may be used up
if (connectionPool.size() > 0) {
connection = (Connection) connectionPool.firstElement();
connectionPool.removeElementAt(0);
}
// Giving away the connection from the connection pool
return connection;
}
public synchronized void returnConnectionToPool(Connection connection) {
// Adding the connection from the client back to the connection pool
connectionPool.addElement(connection);
}
public static void main(String args[]) {
new ConnectionPoolManager();
}
}
can any one help?
The purpose of connection pooling is to maintain a number of open connections to a database so that when your application requires a connection it does not have to go through the potentially resource and time intensive process of opening a new connection.
When an application requires a database connection it 'borrows' one from the pool. When it's done, it gives it back and that connection may be reused at some later point.
Once you have obtained a connection, you use it in your application through the JDBC (Java Database Connectivity) API.
Oracle's basic tutorial for using JDBC can be found at http://docs.oracle.com/javase/tutorial/jdbc/basics/index.html
Another thing to keep in mind is that alot of work has gone into developing connection pools already, and it probably is not necessary to reinvent the wheel, except perhaps as a learning excercise. Apache Tomcat's connection pool implementation can be used outside of Tomcat (for example, in a standalone Java application) and is fairly flexible and easy to configure. It can be found at https://people.apache.org/~fhanik/jdbc-pool/jdbc-pool.html
I would say the code is pretty self explanatory.
You create an instance of the pool, personally, I prefer to use a singleton, but that's another topic
ConnectionPoolManager connectionPoolManager = new ConnectionPoolManager();
Now, every body that wants a connection, is going to need a reference to this manager. When you need to, you request a free connection from the pool...
public void queryDatabaseForStuff(ConnectionPoolManager cpm) throws SQLException {
Connection con = cpm.getConnectionFromPool();
//....
Once you're finished with the connection, you pass it back to the manager...
try {
//...
} finally {
cmp.returnConnectionToPool(con);
}
Now. You might like to investigating a blocking process that will block the current call to getConnectionFromPool while the pool is empty, meaning that it will either throw an exception (if you want to include a time out feature) or a valid connection.
When re-pooling a Connection, you might like to check to see if the Connection has been closed or not and have some kind of revival process to ensure that the pool is awlays close to capcaity...
Please check this link for getting detailed answer - https://examples.javacodegeeks.com/core-java/sql/jdbc-connection-pool-example/
You don't need to recreate your Connection object pool , instead please use the libraries provided by Apache . Please be clear of the following :
1 - Why and what made you think of connection pool ?
2 - Use the following Apache commons-dbcp lib in your Maven project and then use the classes as per documentation .
3. Does this solve all your problems ?
ITs Better to perform the connection pooling via in built API
Like
DBCP or this.
Its always better let these API perform the connection pooling and programmatically creating and maintaining the connection pooling always painful activity.
I am using Java 1.7 and Postgres via the Postgres JDBC drivers. The database connection will be used from a Web Service. In testing, I got the following error:
FATAL: connection limit exceeded for non-superusers
I solved the error by making my connection static, and, only creating once. My question is, is a static connection safe? Is this the right way to do this?
I am using the connection via a ConnectionFactory that looks something like this:
public class ConnectionFactory
{
String driverClassName = "org.postgresql.Driver";
String connectionUrl = "jdbc:postgresql://localhost:5432/dbName";
String dbUser = "user";
String dbPwd = "password";
private static ConnectionFactory connectionFactory = null;
private static Connection conn = null;
private ConnectionFactory()
{
try
{
Class.forName(driverClassName);
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
}
public Connection getConnection() throws SQLException
{
if (conn == null)
{
conn = DriverManager.getConnection(connectionUrl, dbUser, dbPwd);
}
return conn;
}
public static ConnectionFactory getInstance()
{
if (connectionFactory == null)
{
connectionFactory = new ConnectionFactory();
}
return connectionFactory;
}
}
Postgres JDBC driver is documented as thread safe and the connection can be used by multiple threads if so required. If a thread attempts to use the connection while another one is using it, it will wait until the other thread has finished its current operation.
Connection pooling may be used anyway for performance reasons.
Sorry, original post didn't look at your code carefully. Wow. I still can't read. Anyway, third time's the charm. If your code is single threaded - then your fine. If it's multi-threaded, use something like the Commons connection pools to manage your connections. It looks like the driver is thread safe but the connection shouldn't be viewed as thread safe. So, once the driver is loaded you can safely call getConnection on the driver from multiple threads, but the connection shouldn't be shared across threads.
Currently, I load the below custom driver (TestDriver.java), get a connection, create a Statement, execute a query, gets the results and close the connection. I open and close a connection for each query. Is this common practice or is there an standard way to share the open connections?
public static void main(String[] args) {
Class.forName("com.sql.TestDriver");
java.sql.Connection conn = DriverManager.getConnection("jdbc:test://8888/connectme", props);
Statement stmt = conn.createStatement;
ResultSet rs = stmt.executeQuery("select * from table");
//loop through rs and pull out needed data
conn.close();
}
public class TestDriver implements java.sql.Driver{
private final TestSchema schema;
private Properties props = null;
static {
try {
DriverManager.registerDriver(new TestDriver());
} catch (SQLException e) {
e.printStackTrace();
}
protected TestDriver() throws SQLException {
schema = TestSchemaFactory.getInstance().getDbSchemaFromFile(SCHEMA_FILE);
//loads in and parses a file containing tables, columns used for business logic
}
public Connection connect(String url, Properties info)
throws SQLException {
TestSqlConnection conn=null;
//connect logic here
return conn; //will return an instance of TestSqlConnection
}
#Override
public boolean jdbcCompliant() {
return false;
}
}
Yes, it's more common to use a database connection pool. This will allow connections to be reused without the overhead or closing/re-opening. Here's a link to DBCP which is one implementation of a database connection pool: http://commons.apache.org/dbcp/
Ideally you should write a separate factory class (can be static)
say ConnectionFactory which returns a connection object.
Also I see that you are not using try/catch/finally block while creating
connection.I strongly suggest to close the connection in finally
clause otherwise you program may suffer from connection leak if any
exception is raised and causes abrupt behavior.
Ideally you should close the connection after your operation is complete in finally
clause.In web based application if you are using connections pool
then closing connection will return the connection back to pool and
will be available for use.