I'm trying to implement a solution with c3p0 for the first time. I understand how to initialize the connection pool and "checkout" a Connection from the pool as follows:
ComboPooledDataSource cpds = new ComboPooledDataSource();
cpds.setDriverClass(driverClass);
cpds.setJdbcUrl(url);
cpds.setUser(username);
cpds.setPassword(password);
Connection conn = cpds.getConnection(username, password);
But I am having trouble finding out how to "checkin" an already used Connection to go back into the pool. How would I go about doing this? Is there something that I'm doing wrong here?
Freeing up is totally transparent to the user. See here for further explanation.
Be shure to close() the Connection and hold no further reference (that would avoid proper GC).
I believe the connection is returned to the pool when you close it.
Related
I am using hikaricp as my database connection pool. I am closing the connection when I am done with my SQL statement by calling close on the connection which I believe you should return the connection proxy back to the pool . Yet, I see the following warning (not error) message and I have to wonder whether its an issue that needs to be addressed because I'm not cleaning up my connection resources properly. I am not using a try with resources but using a try catch finally (I close the connection in the finally & I realize that in certain conditions, the finally may actually not get called but it is being called in my case). any thoughts?
2014-09-15 13:59:26,083 WARN c.z.h.p.LeakTask [Hikari Housekeeping Timer (pool wmHikariCp)] Connection leak detection triggered, stack trace follows java.lang.Exception
at com.abc.test.DBConnPool.getConnection(DBConnPool.java:71)
at com.abc.test.TestProj.callDB(TestApp.java:30)
at com.abc.test.TestProj.main(TestApp.java:81)
Can you confirm whether you are indeed releasing the connection back to the pool? Can you use try with resources (in addition to increasing threshold as Brett mentioned):
try (Connection conn = DBConnectionPool.getConnection();
PreparedStatement ps = conn.prepareStatement(preparedQuery);) {
and the resultset (because some drivers/databases may not clean out resultset when connection is cleaned though not sure if this is still valid for new drivers/databases but I'm not sure what you are using):
try (ResultSet rs = ps.executeQuery();) {
Hope it helps.
There is a possibility that you are merely using the connection longer than the leak detection timeout. The leak detection is a threshold for how long a connection is out of the pool. Try increasing the threshold to a longer timeout.
We have BoneCP library managing our connection pools. I'd like to know if the following statement will return the connection back to the pool.
statement = conn.createStatement();
....
lots of code.
....
Connection conn = statement.getConnection();
statement.close();
conn.close();
Will the above code close the connection and put the connection back into the pool?
Update:
I'm asking this question because when I run the statistics on connectionpool, i still see the conPool.getTotalLeased() showing that 2 connections are being used. But, I've closed the connections using the above mechanism.
The whole sense of a pool is to hold already established connections to your database. When you retrieve a connection from your pool you save the time to connect to your database.
What you are seeing is the pool holding your connections so it is all fine.
When you close your connection, it is only returned to the pool and marked as available for your next retrieval.
Yes it does moves the connection back to the pool. There was a mistake when getting the connection from the pool, fixed it, now i'm not seeing the 2 connections in the totalLeased() method.
Mistake that I found
conPool.getConnection(); // loitering connection which we see in the getTotalLeased();
..
Statement st = conPool.getConnection().getStatement(); //we have handle to this connection.
return st;
Our standard code section for using JDBC is...
Connection conn = getConnection(...);
Statement stmt = conn.conn.createStatement (ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_READ_ONLY);
ResultSet rset = stmt.executeQuery (sqlQuery);
// do stuff with rset
rset.close(); stmt.close(); conn.close();
Question 1: When using Connection Pool, should one close the Connection at the end? If so, isn't the purpose of pooling lost? And if not, how does the DataSource know when a particular instance of Connection is freed up and can be reused? I am a little confused on this one, any pointers appreciated.
Question 2: Is the following method anything close to standard? Looks like an attempt to get a connection from the pool, and if DataSource cannot be established, use the old fashioned DriverManager. We are not even sure which part is getting executed at runtime.
Repeating the question above, should one close the Connection coming out of such a method?
synchronized public Connection getConnection (boolean pooledConnection)
throws SQLException {
if (pooledConnection) {
if (ds == null) {
try {
Context envCtx = (Context)
new InitialContext().lookup("java:comp/env");
ds = (DataSource) envCtx.lookup("jdbc/NamedInTomcat");
return ds.getConnection();
} catch (NamingException e) {
e.printStackTrace();
}}
return (ds == null) ? getConnection (false) : ds.getConnection();
}
return DriverManager.getConnection(
"jdbc:mysql://"+ipaddy+":"+dbPort +"/" + dbName, uName, pWord);
}
Edit: I think we are getting the pooled connection since we do not see a stack trace.
When using Connection Pool, should one close the Connection at the end? If so, isn't the purpose of pooling lost? And if not, how does the DataSource know when a particular instance of Connection is freed up and can be reused? I am a little confused on this one, any pointers appreciated.
Yes, certainly you need to close the pooled connection as well. It's actually a wrapper around the actual connection. It wil under the covers release the actual connection back to the pool. It's further up to the pool to decide whether the actual connection will actually be closed or be reused for a new getConnection() call. So, regardless of whether you're using a connection pool or not, you should always close all the JDBC resources in reversed order in the finally block of the try block where you've acquired them. In Java 7 this can be further simplified by using try-with-resources statement.
Is the following method anything close to standard? Looks like an attempt to get a connection from the pool, and if DataSource cannot be established, use the old fashioned DriverManager. We are not even sure which part is getting executed at runtime. Repeating the question above, should one close the Connection coming out of such a method?
The example is pretty scary. You just need to lookup/initialize the DataSource only once during application's startup in some constructor / initialization of an applicationwide DB config class. Then just call getConnection() on the one and same datasource throughout the rest of application's lifetime. No need for synchronization nor nullchecks.
See also:
Is it safe to use a static java.sql.Connection instance in a multithreaded system?
Am I Using JDBC Connection Pooling?
The pools typically return you a wrapped Connection object, where the close() method is overridden, typically returning the Connection to the pool. Calling close() is OK and probably still required.
A close() method would probably look like this:
public void close() throws SQLException {
pool.returnConnection(this);
}
For your second question, you could add a logger to show whether the bottom block ever runs. I would imagine though you'd only want one way or the other for the configuration of your database connections. We solely use a pool for our database accesses. Either way, closing the connection would be pretty important to prevent leaks.
Actually, the best approach to connection management is to not farm them out to any code anywhere.
Create a SQLExecutor class that is the one and only location which opens and closes connections.
The entire rest of the application then pumps statements into the executor rather than getting connections from the pool and managing (or mismanaging them) all over the place.
You can have as many instances of the executor as you want, but no one should be writing code that opens and closes connections on its own behalf.
Conveniently, this also lets you log all your SQL from a single set of code.
I have an application that connects to MySQL using JDBC. There are cases where the JDBC connection lies idle for hours (maybe even days) and its loosing its connection to MySQL and then excepts when it tries to execute a query. What is the best solution for this?
Keeping the connection open for an undertemined time is a bad practice. The DB will force a close when it's been open for a too long time. You should write your JDBC code so that it always closes the connection (and statement and resultset) in the finally block of the very same try block where you've acquired them in order to prevent resource leaking like this.
However, acquiring the connection on every hiccup is indeed a pretty expensive task, so you'd like to use a connection pool. Decent connection pools will manage the opening, testing, reusing and closing the connections themselves. This does however not imply that you can change your JDBC code to never close them. You still need to close them since that would actually release the underlying connection back to the pool for future reuse.
There are several connection pools, like Apache DBCP which is singlethreaded and thus poor in performance, C3P0 which is multithreaded and performs better, and Tomcat JDBC for the case that you're using Tomcat and wouldn't like to use the builtin DBCP due to bad performance.
You can create connection pools programmatically, here's an example with C3P0:
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dbname");
dataSource.setUser("username");
dataSource.setPassword("password");
Do it once during application's startup, then you can use it as follows:
Connection connection = null;
// ...
try {
connection = dataSource.getConnection();
// ...
} finally {
// ...
if (connection != null) try { connection.close(); } catch (SQLException ignore) {}
}
When you're running inside a JNDI-capable container like a servletcontainer (e.g. Tomcat), then you can also declare it as a java.sql.DataSource (Tomcat specific manual here). It will then use the servletcontainer-provided connection pooling facilities. You can then acquire the datasource as follows:
DataSource dataSource = (DataSource) new InitialContext().lookup("java:comp/env/jdbc/YourDataSourceName");
There are libraries, such as Apache's DBCP which can do connection pooling. A part of this is they can be setup to automatically test the connection when you go to use it (such as "SELECT NOW() FROM DUAL", or something else harmless) and automatically re-establish the connection transparently if necessary, allowing your application to pretend that the connection is everlasting.
Check here:
http://download.oracle.com/javase/tutorial/jdbc/basics/connecting.html
Basically, you should use DataSource and always do a getConnection() before using it. DataSource, unless there's something terribly wrong, will reconnect if necessary.
I am trying to connect to DB using the standard JDBC way
connection = DriverManager.getConnection(url, username, password);
Is there a maximum value of timeout on the connection, how long does a connection live, can I increase the value. I want in cases the connection to be open forever , is it a good idea.
You can set the Timeout on the DriverManager like this:
DriverManager.setLoginTimeout(10);
Connection c = DriverManager.getConnection(url, username, password);
Which would imply that if the connection cannot open within the given time that it times out.
In terms of keeping a connection open forever, it is possible if you do not close the connection but it may not be a good idea. Connections should be closed as soon as you are finished with them.
If you want to optimise the opening and closing of connections then you can use a connection pool.
The value is usually DB-controlled. You have no control over it using code. It depends on the DB server used. It is usually around 30 minutes up to one hour.
On the other hand, keeping a Connection open forever is a very bad idea. Best practice is to acquire and close Connection, Statement and ResultSet in the shortest possible scope to avoid resource leaks and potential application crashes caused by the leaks and timeouts.
True, connecting the DB is an expensive task. If your application is supposed to run a relatively long time and to connect the DB fairly often, then consider using a connection pool to improve connecting performance. If your application is a webapplication, then take a look in the appserver's documentation, it usually provides a connection pooling facility in flavor of a DataSource. If it is a client application, then look for 3rd party connection pooling libraries which have proven their robustness with years, such as Apache Commons DBCP (commonly used, used in lot appservers), C3P0 (known from Hibernate) and Proxool (if you want XA connections).
Keep in mind, when using a connection pool, you still have to write proper JDBC code, i.o.w. acquire and close all the resources in the shortest possible scope. The connection pool will on its turn worry about actually closing the connection or just releasing it back to pool for further reuse.
You may get some more insights out of this article how to do the JDBC basics the proper way.
Hope this helps and happy coding.
Here is how to do it with Connector/J MYSQL driver:
String qqq = "jdbc:mysql://localhost/Test?connectTimeout=TIME_IN_MILLIS";
conn = DriverManager.getConnection(qqq, db_user, db_pass);
It worked for me after setLoginTimeout() did nothing.
Just reposting a more complete repost of a comment from user flamming_python as answer because it worked for me:
dbConnectionString = "jdbc:mysql://"+dbHost+":"+dbPort+"/"+dbTable+"?user="+dbUser+"&password="+dbPassword;
Properties properties = new Properties();
properties.put("connectTimeout", "2000");
dbConnect = DriverManager.getConnection(dbConnectionString, properties);
Original comment:
"LoL # your threads - you can do it quite simply by creating a Properties object prop, then prop.put("connectTimeout", "2000") (where the "2000" is the timeout in ms), and then pass your prop object to the DriverManager.getConnection() method along with your url"
As bestro suggested, it's possible to use a future with an associated timeout. For example:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Connection> future = executor.submit(new Callable<Connection>() {
#Override
public Connection call() throws Exception {
Connection con = DriverManager.getConnection(url, username, password);
return con;
}
});
Connection con = null;
try {
con = future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
Logger.getLogger(Scratch.class.getName()).log(Level.SEVERE, null, ex);
}
executor.shutdownNow();
if (con == null) {
System.out.println("Could not establish connection");
} else {
System.out.println("Connection established!");
}
You can use ExecutorService interface from Java. Below is a sample of what you need to do.
Future<Boolean> future = executor.submit(YOUR_METHOD);
future.get(TIMEOUT_YOU_NEED, TimeUnit.SECONDS);