13

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?

rook
  • 66,304
  • 38
  • 162
  • 239

3 Answers3

20

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");
informatik01
  • 16,038
  • 10
  • 74
  • 104
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • why not keep the connection as a class member, check if it is closed when you plan to use and initiate new connection if closed? What would be wrong with this except holding onto a little of memory for a while? – Buddy Oct 06 '15 at 06:32
  • 3
    @EB: It's threadunsafe. Related: http://stackoverflow.com/q/9428573 You should use one completely separate connection per thread and transaction. They can be kept open and be reused after they've done their threadlocal transactional job, but that's already exactly what a connection pool does. A connection pool does not physically close the connection, it just keeps it open and tests it before releasing (as already answered in this post) – BalusC Oct 06 '15 at 06:33
4

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.

MBCook
  • 14,424
  • 7
  • 37
  • 41
  • This is the way to go. You can even set it up to do a dummy SELECT before return the connection to client so you know it will work. – Amir Raminfar Nov 17 '10 at 22:18
0

Check here:

Basically, you should use DataSource and always do a getConnection() before using it. DataSource, unless there's something terribly wrong, will reconnect if necessary.

icyrock.com
  • 27,952
  • 4
  • 66
  • 85