29

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.

Martin Schröder
  • 4,176
  • 7
  • 47
  • 81
kal
  • 28,545
  • 49
  • 129
  • 149

6 Answers6

38

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.

Emre
  • 1,023
  • 2
  • 9
  • 24
Vincent Ramdhanie
  • 102,349
  • 23
  • 137
  • 192
  • 5
    Hmm, IIRC this only sets the timeout how long the DriverManager has to wait before the DB returned a connection. It does not set the connection's timeout. Also see: http://java.sun.com/javase/6/docs/api/java/sql/DriverManager.html#setLoginTimeout%28int%29 – BalusC Nov 05 '09 at 22:15
  • 1
    Thats right @BalusC. As I mentioned that timeout is only how long the DriverManager waits for a connection not how long the connection stays open. – Vincent Ramdhanie Nov 05 '09 at 22:40
  • 2
    I must however admit (and you probably also) that this is the correct answer on the question as literally phrased in topic's subject. But the actual question in the topic message turned out to be something different. – BalusC Nov 06 '09 at 13:42
  • 2
    `DriverManger.setLoginTimeout(10)` doesn't work for me with the MySQL driver. I think the only way to do it is with [threads](http://stackoverflow.com/questions/4850957/how-to-force-time-out-the-drivermanager-getconnection-method-call). – styfle Sep 24 '11 at 18:46
  • 2
    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 – flamming_python Apr 11 '14 at 20:08
  • The problem is that even if it compiles OK, it never throws the SQLTimeoutException really. :-( – Gangnus Aug 24 '16 at 14:58
  • For postgres jdbc driver you can use [loginTimeout (int)](https://jdbc.postgresql.org/documentation/use/) – yokus Aug 29 '23 at 11:34
34

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.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 3
    DBCP is a horrible, *horrible* connection pool. Never use it. – erickson Nov 06 '09 at 01:00
  • Interesting. I've never had serious problems with it when used in flavor of a Tomcat 6.0 managed datasource. Care to elaborate? – BalusC Nov 06 '09 at 02:22
  • 7
    Well, you want to use a pool when resources are "expensive" (take some time to create). DBCP (or really the underlying pool) holds a lock on the entire pool while new objects are being produced. This prevents threads that have finished with a resource and are merely trying to return it to block. Meanwhile, other threads are blocked trying to get those resources. Because these lock acquisitions aren't using the concurrent package, they aren't interruptible. This hurts performance under normal conditions. If something is actually wonky with the DB, it gets *really* ugly, really fast. – erickson Nov 06 '09 at 23:04
  • 4
    Yes, good point. For Tomcat better replace by `org.apache.tomcat.jdbc.pool.DataSourceFactory`. Thanks for heads up, +1. – BalusC Nov 06 '09 at 23:28
  • Universal Connection Pool (UCP) is a Java connection pool that works well. Check out UCP Developer's guide (https://docs.oracle.com/database/121/JJUCP/toc.htm) for more details. All you need ucp.jar in the classpath. – Nirmala Jul 27 '16 at 16:36
10

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.

Unihedron
  • 10,902
  • 13
  • 62
  • 72
QQ_QQ
  • 123
  • 1
  • 7
  • 5
    it's wrong `connectTimeout=TIME_IN_MILLIS` because it is `connectTimeout=TIME_IN_SECONDS` more info here http://dev.mysql.com/doc/refman/5.1/en/mysql-command-options.html#option_mysql_connect_timeout – hcarrasko Mar 12 '15 at 14:03
  • No, `connectTimeout=TIME_IN_MILLIS` refer to this [document](https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-reference-configuration-properties.html) – You're awesome Aug 23 '19 at 08:54
7

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"

Felix
  • 106
  • 1
  • 4
  • This does work for me and there is no timeout error now. From javadoc of the API, "normally at least a "user" and "password" property should be included". I tested h2 db. – Leon Apr 04 '18 at 05:52
2

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!");
}
Fidel
  • 7,027
  • 11
  • 57
  • 81
-3

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);
Unihedron
  • 10,902
  • 13
  • 62
  • 72
bestro
  • 25
  • 2
  • 1
    A terrible idea. This creates a ThreadFactory, a Thread, runs the connect in parallel, and implements a timeout in `get()`, while leaving the actual connection to proceed with no real way of aborting itself. – user207421 Nov 04 '15 at 06:07