I have been playing around with JDBC drivers. I would like some advice from the experience code masters out there. I was wondering if this is a good way to find if am connected to a database. If it is not, could someone let me know how would they do it?
Connection con = null;
try {
con = DriverManager.getConnection("jdbc:mysql://localhost/"+database+"?+user="+user+"&password="+password);
} catch (SQLException e) {
System.out.println(e.getMessage());
if (con != null) {
System.out.println("hello");
} else {
System.out.println("Not Connected!");
}
}
I would really appreciate all helpful comments. Many thanks in advance.
If the getConnection method returns normally, and does not throw an exception, then a connection to the database has been made. The logic within the catch clause is unrequired, because if an exception is caught a connection was not established.
The returned Connection object must be close()d (as many of the JDBC classes must, such as Statements and ResultSets for example). Assuming Java7, a convenient way to ensure the Connection is closed is using the try-with-resources statement:
try (Connection con = DriverManager.getConnection(...))
{
}
catch (final SQLException e)
{
}
As stated by SnakeDoc in the comments this may be impractical in production systems because establishing a connection to the database is a typically expensive operation.
The JDBC API will perform these checks for you. Whenever you perform a database operation, such as opening a connection, executing a statement, it will check to see if the connection is valid. If not it will throw an exception.
For example, the method Connection.createStatement throws the following:
SQLException - if a database access error occurs or this method is called on a closed connection
All you have to do is some basic exception handling. Surrounding your JDBC calls with try-catch blocks is one way do this. You could also throw the exception and handle it somewhere else.
That's definitely a good way of doing it! If conn can't be initialised it's either your connection string that is wrong or the database is down.
Related
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try
{
conn = geting the connection object ( using DriverManager.getConnection() method or using connection pool)
stmt = conn.createStatement ("select ...");
// some other logic here
}
catch (SQLException e)
{
// handling the exceptions
}
finally
{
}
Here my question is while closing the connection object in the following cases what are the problems it will come.
Assume if there is no exception occurred, in try block there it self closing the connection object.
try {
// same above code
stmt.close();
conn.close();
} catch(Exception ex) {
// handling the exceptions
} finally {
}
If some exception is occured so it will goes to catch block, there it self closing the connection object.
try {
// same above code
} catch(Exception ex) {
// handling the exceptions
stmt.close();
conn.close();
} finally {
}
Closing the connection object in finally block.
try {
// same above code
} catch(Exception ex) {
// handling the exceptions
} finally {
stmt.close();
conn.close();
}
Difference between closing the connection object using close() method and closing the pooled connection using close().
Note: Please don't say closing the connection object in finally block is good. I know that one. If i keep the close connection in try block, catch block is there any problems please explain.
It is recommended to close the connection in the finally block because if you have multiple catch blocks (as you should: you should never catch generic Exception) you will not have to re-write the closing statements.
A finally block will always be executed after a try, no matter what happens. So if you get a NullPointerException, or some other exception you didn't handle, with the finally block you will be sure that your resources are closed properly.
But if you are on java 7, I'd suggest to use the try-with-resources block
As database is consuming more resources, it is always recommended to close your connection after your processing is done whether successfully or not.
You said that adding conn.close() in try, this is fine if your query runs without any exception and what if your query has any issues, the connection would not be closed. So it is always recommended to close your connection in finally block which is executed always irrespective of whether exception occurred or not. Also if you try to put the closing statement in catch block and your trying to handle multiple exceptions you will need to repeat your code which is not recommended.
Answer is that 'We must close the connection after using it.' But the actual question is why we must close the connection after using?.
1.) When we create a connection with a remote database server lets say MySQL Server, It also keeps a connection open for you. Due there is a also a limitation/configuration at database server end for number of connection allowed. If we don't close the connection from our end it will remain open and such way after a short while number of allowed connections will be exceeded at database server end and we will not be able to make further connection with that database.
2.) Auto release connections time setting at database server side.
If we don't close connection from our end and we don't execute any query for certain period of time (As I think default time setting in MySql is 28800 sec. means 8 Hrs. Although we can change it.) it will automatically release the connection from server end.
Important! What will happen in that situation when your jdbc Connection object is really released at database server end and you think it is still connected because you never disconnected/closed it and you are trying to executing query on that connection using statement. Really critical.
That's why we must always close the connection and execute statement on connected connection object.
The finally block is always executed, including the following cases:
Normal termination of the try-block.
Exceptional termination of the try-block when exception is handled in some catch.
Exceptional termination when exception is propagated to the caller.
A return statement in the middle of the block:
try {
if(something) return false; // finally is executed here as well
...
} finally { ... }
A break or continue statement if the whole try-catch is inside the loop:
while(condition) {
try {
if(something) continue; // finally is executed here
else if(somethingElse) break; // finally is executed here
...
}
finally {
}
}
Thus no matter how you exit the try block, the finally will be executed and you should not care about checking every possible exiting way. This is really convenient.
finally block always execute :
try{
// code logic
}catch(SQLException ex){
// catch exception
}finally{
if (dbConnection != null){
dbConnection.close();
}
}
What happens if an exception you're not handling gets thrown? (I
hope you're not catching Throwable...)
What happens if you return from inside the try block?
What happens if the catch block throws an exception?
A finally block makes sure that however you exit that block (modulo a few ways of aborting the whole process explicitly), it will get executed. That's important for deterministic cleanup of resources.
Note : Also for preventing application resource leaking we have to close connection anyway..!!
Thanks.!!
You can close connection in try or in catch block, but will tell you why is good to close connection in finally Block
Suppose you have try catch block as below:
try{
stmt1..
stmt2..
conn.close
}
catch(exception e){
}
Now suppose exception is raised by stm1 then your connection will remain open.
Now consider you are closing connection in catch block..what if no exception raised then control will never come in catch block.. here connection is still open.. I hope i am able to clear few of you doubts.
I have created a Database class which uses a static connection object in order to be used in common between instances of itself. my question is that is there any problem with this approach or not?
class Database {
private static Connection connection = null;
public Database() {
if(connection == null){
...
connection = DriverManager.getConnection(...);
...
}
}
}
If you are going to have many (hundreds) of queries per second then implementing a connection pool is the way to go. See the answer to this question for more details. However, if you a Java novice (we all were one day!) then I don't imagine you will be needing this requirement, and probably will struggle to implement it.
Instead, the simple pattern of creating a new connection if required, and then closing it when finished will be the best way to go forward for you. Below is a modified version of your Database class which I think is a good way to move forward.
class Database {
private Connection con = null;
private final String connectionString;
public Database(String connectionString) {
this.connectionString = connectionString;
}
public void connect() throws SQLException {
if (con != null // if the connection exists
&& !con.isClosed() // and has not been closed
&& con.isValid(0)) { // and appears to be functioning (with a test timeout of 0ms)
return; // skip connection creation
}
// create the connection
con = DriverManager.getConnection(connectionString);
}
public void testFunction() {
try {
connect();
// .. do some stuff with the connection ..
} catch (Exception e) {
// log or otherwise deal with the error
} finally {
try {
con.close();
} catch (Exception e) {
System.err.println("Failed to close connection: " + e.toString());
}
}
}
}
Some things to note about this solution:
It is not very efficient - creating a new connection always takes more time than using an existing one
This class if not thread safe - if you need this requirement, I recommend using a thread pool. However, if you create a new instance of this class per thread then it will be thread safe (as there is not static connection to worry about!)
It does do the job - certainly for simple cases. I use the model for a relatively low volume database which has approx 50-100 connections made/closed per minute and it does not add a noticeable lag
It is very robust - nothing is safer than opening and closing a connection per query. You are guaranteed to be able to handle a connection failure per query, and the connection will always be closed (unless it already has been).
Disclaimer The solution above is not a particularly amazing solution. However, I believe it is simple to implement and a good way for a Java novice to get to know the ropes before jumping into external libraries.
There is nothing wrong with creating an object to manage your connections, however, connections should be opened and closed and can be used in multi-threaded environments, so having a static connection is not a good idea. For a method that needs a connection, get a connection use it, close it. Even if you are not using it in a multi-threaded environment, the connection can time-out, then you need to constantly check if the connection is up and available, instead of just saying, get me a connection, use the connection, close it.
I'm writing some Java application that uses Java DB (i.e. Apache Derby) as database. I use the following method to connect to database:
Connection getConnection() throws SQLException {
EmbeddedDataSource ds = new EmbeddedDataSource();
ds.setDatabaseName(dbUri);
ds.setPassword(password);
ds.setUser(username);
Connection conn = ds.getConnection();
conn.setSchema(schema);
return conn;
}
This works ok, but sometimes I get the following exception:
java.sql.SQLException: Another instance of Derby may have already booted the database
This happens when I run my application and at the same time SQuirreL SQL Client is connected to my database. So everything works as expected, but I would like to be able to check for this in my getConnection() method. I other words, I would like to check if any sessions are opened to my database, and for example, close them, throw my own exception or display error dialog box. I don't know how to do this.
Thx
Rather than declaring that your application "throws SQLException", you can use a "try" block to catch the SQLException, then examine the exception and decide if it is the "Another instance of Derby" exception or not.
Then, you can throw your own exception from your "getConnection" method accordingly.
I modified my getConnection() method to something like below. It does what i want:
Connection getConnection() throws SQLException, DAOConnection {
EmbeddedDataSource ds = new EmbeddedDataSource();
ds.setDatabaseName(dbUri);
ds.setPassword(password);
ds.setUser(username);
Connection conn = null;
try {
conn = ds.getConnection();
} catch (SQLException e) {
// check if cannot connect due to "Another instance of
// Derby may have already booted the database".
// The error code of this exception is 45000.
if (e.getNextException().getErrorCode() == 45000) {
throw new DAOConnection(e.getNextException().getMessage());
}
throw new SQLException(e);
}
conn.setSchema(schema);
return conn;
}
Prevention is better than cure. IMO, catching exception and then realizing it was duplicate Derby server started is not an ideal design. Better would be to prevent duplicate instantiation. If possible you can synchronize your getConnection() method or make it part of a singleton class or load the embedded Derby driver from static initializer block of a startup/main class which is loaded only once by JVM and hence Derby will be started only once. Something like following in the main/startup class should do the trick:
static {
try {
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
}
catch(Exception e){
.....
}
}
Per the link here http://db.apache.org/derby/docs/10.3/devguide/tdevdvlp38381.html loading the Driver should start the Derby embedded system.
According to JAVA documentation, Connection#commit() can throw SQLException. My question is whether or not a rollback should still be issued in this scenario.
For example:
Connection con = null;
try {
// assume this method returns an opened connection with setAutoCommit(false)
con = createConnection();
// do DB stuff
con.commit();
} catch (SQLException e) {
if (con != null) {
// what if con.commit() failed, is this still necessary,
// will it hurt anything?
con.rollback();
}
} finally {
if (con != null) {
con.close();
}
}
I actually wrapped the con.rollback() call into another method which ignores any exceptions thrown by it, so I think I'm ok here. I just wondered if this was the best way of handling things.
Rollback is important even if commit failed, according to the Java 1.6 JDBC docs:
It is strongly recommended that an application explicitly commits or
rolls back an active transaction prior to calling the close method. If
the close method is called and there is an active transaction, the
results are implementation-defined.
This means that if you do not explicitly invoke rollback, some JDBC implementation might invoke commit before closing the connection.
Another good reason to rollback is as Xepoch suggested and when using a connection pool it is even more important.
When getting a connection from a connection pool, most implementations will execute connection.setAutoCommit(defaultAutoCommit) before giving you the connection and according to the JavaDocs:
If this method is called during a transaction and the auto-commit mode
is changed, the transaction is committed
If the connection.rollback() throws an exception - then it is a tricky one...
I would do explicit rollback just for clean-up purposes. Although changes won't be persisted in db either way, it seems nice to explicitly let database know that you're done here. Just like the way you close connection explicitly, without waiting for Connection object to be garbage-collected.
This is, obviously, not a technical answer and I would also be interested to learn whether there's a practical point in doing so.
"Returns an open connection?" If that connection is shared in a pool (and could be in the future) you don't want another transaction committing your earlier work. I've seen MANY customer/solution cases of plugging in pooled connection driver that comply with JDBC interfaces and Connection.close() can also be used to just return the Connection back to a pool.
Also, better try{}catch{} your rollback() (edit, just read your whole post, but I always like to log an exception on rollback)
The usual way I do this is:
boolean bSuccess = false;
Connection con = null;
try {
// assume this method returns an opened connection with setAutoCommit(false)
con = createConnection();
// do DB stuff
bSuccess = true;
} catch (SQLException e)
{
}
finally
{
try
{
if (con != null)
{
if(bSuccess)
con.commit()
else
con.rollback();
con.close();
}
}
catch(SQLException sqle)
{
log("Log the error here");
// do nothing we tried
}
}
That being said I have never seen a commit or a rollback fail if the queries worked.
If you have pending transactions then most databases have tools to free them. Most app servers will keep retrying the commits and rollbacks until they can connect.
You might want to look at this post: Is it necessary to write ROLLBACK if queries fail?
Say you have the following code:
Connection conn;
try
{
conn = ... // get connection
conn.setAutoCommit(false);
... // Do some modification queries and logic
conn.commit()
} catch(SQLException e)
{
conn.rollback() // Do we need this?
conn.close()
}
In this code, if there is an exception, is it better style to just close the connection (since autocommit is off), or to explicitly roll back and then close the connection? There are no save points.
I feel that it might make sense to add the rollback call because:
1) Someone, in the future, might add save points but forget to add the rollback
2) It improves readability
3) It shouldn't cost anything, right ?
But obviously, none of these is particularly compelling. Any standard practice?
Note: I'm aware of the need to do a repeat try/catch on closing and rollback. I actually have a middleware that abstracts the database access and takes care of that, but I was wondering whether adding it was superfluous.
The normal idiom is the following:
public void executeSomeQuery() throws SQLException {
try (Connection connection = dataSource.getConnection()) {
connection.setAutoCommit(false);
try (PreparedStatement statement = connection.prepareStatement(SOME_SQL)) {
// Fire transactional queries here.
connection.commit();
} catch (SQLException e) {
connection.rollback();
throw e;
}
}
}
Note that Java 7's try-with-resources statement always implicitly calls close() on the resource when the try block finishes, as if it happens in finally.
Calling rollback() is also mandatory when it concerns a pooled connection. Namely, it will reset the transactional state of the connection. The close() of a pooled connection won't do that, only the commit() and rollback() will do that. Not calling rollback() may lead that the next lease of the pooled connection will still have the (successful) queries of the previous transaction in its memory.
See also javadoc of Connection#close() (emphasis not mine):
It is strongly recommended that an application explicitly commits or rolls back an active transaction prior to calling the close method. If the close method is called and there is an active transaction, the results are implementation-defined.
Closing should rollback because it will not commit when the resources are release, but it's good to have your error handling be specific, so if you want to rollback on an exception, do that. Then you can do your cleanup in a finally{} block. The rollback() occurs only on error, in which case your commit() is not successful or was not even reached.
Connection conn = null;
try {
conn = ...
...
conn.commit();
}
catch (SQLException e) {
if (conn != null) {
conn.rollback();
}
}
finally {
if (conn != null) {
conn.close();
}
}