Where to close statements in JDBC - java

I am using JDBC to retrieve data from a database. I understand that a Statement needs to be closed after it is used. However, I keep run into the same error telling me that no operation is allowed after the statement is closed. The structure of my code is like
public void foo() {
Statement;
try {
} catch{
}
Statement.close();
}
In my code, I need to call this function repeatedly. I was wondering where to close the Statement.
Thanks

According to the Javadocs:
Statement.close() Releases this Statement object's database and JDBC resources immediately instead of waiting for this to happen when it is automatically closed. It is generally good practice to release resources as soon as you are finished with them to avoid tying up database resources.
Which means you should close it after you done and not planning to use it again. I would, actually pay more attention to closing your Connection.
In your method which you say you call repeatedly you are calling Statement.close() which means that you can only use it once since after the first call you Statement is closed and cannot be used anymore.
It would be nice to see some of your code if you want a better answer

Note that JDBC resources should always be closed, so, its better to put that to the 'finally' block.
You can also consider Spring DAO usage - it is a thin wrapper on top of JDBC and covers most of JDBC boilerplate stuff.

ResultSets also need to be closed.
It sounds like you might be doing something like accessing a Blob, the Blob object often goes back through the connection to read the byte data from the database. So read all of the byte[] data before you close the connection. If that's not possible because there's too much data and you are trying to stream the bytes then you're just going to have to stick the connection somewhere safe and call close on it later.
Close statements should go into finally blocks, and be null protected - but it's such common and ugly code so stick in a static method somewhere.
public List someMethod() {
Statement stmt;
ResultSet rset;
try {
stmt = con.createStatement();
rset = stmt.executeQuery(....);
List resultList = ...create a list
// get the data from the rset
return resultList;
} catch (SQLException ex) {
throw new MyDatabaseException(ex);
} finally {
}
}
public class DatabaseUtils {
public void close(Statement stmt, ResultSet rset) {
try {
if (rset != null) {
rset.close();
}
} catch (SQLException ex) {
throw new MyDatabaseException(ex);
} finally {
if (stmt != null) {
throw new MyDatabaseException(ex);
}
}
}
}

Related

In try/finally, does it matter what's inside the try?

Is there any functional difference?
Connection c = null;
try {
c = getConnection();
c.doStuff();
} finally {
if (c!=null) c.close();
}
vs
Connection c = null;
c = getConnection();
c.doStuff();
try {
} finally {
if (c!=null) c.close();
}
vs
Connection c = null;
try {
c = getConnection();
} finally {
if (c!=null) c.close();
}
c.doStuff();
I feel that all of them will do the same thing in all cases
Craig already addressed the unhandled exception issue, but I wanted to make it clear. I coded up two examples (the last is just bad because you could be working with a broken connection after an exception has occurred, don't do that). Here is a simple example that throws an ArrayIndexOutOfBoundsException:
class TryCatchFinally {
static int [] array = new int[1];
public static void main(String [] args) throws Exception {
if (args[0].startsWith("1")) {
version1();
} else if (args[0].startsWith("2")) {
version2();
}
}
static int version1() {
int r = 0;
try {
System.out.println("In Try.");
return array[1];
} catch (Exception e) {
System.out.println("In Catch.");
} finally {
System.out.println("In Finally.");
}
System.out.println("In Return.");
return r;
}
static int version2() {
int r = array[1];
try {
System.out.println("In Try.");
} catch (Exception e) {
System.out.println("In Catch.");
} finally {
System.out.println("In Finally.");
}
System.out.println("In Return.");
return r;
}
}
And here is the execution:
(TryCatchFinally)$ javac *.java
(TryCatchFinally)$ java TryCatchFinally 1
In Try.
In Catch.
In Finally.
In Return.
(TryCatchFinally)$ java TryCatchFinally 2
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 1
at TryCatchFinally.version2(TryCatchFinally.java:24)
at TryCatchFinally.main(TryCatchFinally.java:7)
(TryCatchFinally)$
As you can see in the first version an exception handler was registered because the exception occurred within the context of a try block. In the second version there was no registered exception handler and the default exception handler was invoked (meaning an uncaught exception).
An exception that occurs outside of a try-finally block is by definition an unhandled exception. That being the case, you don't have any guarantees about how the operating system or runtime will deal with it. Chances are good that an exception unwind won't be triggered, your code will simply abort (maybe abend describes it better in this discussion--"abnormal end"), and your finally block will never execute.
The point of try-finally is to guarantee that code cleanup occurs, and occurs in the correct context.
You must be thinking that the code in the finally block is always going to execute no matter what, and that it is going to execute after the entire method finishes, therefore it doesn't matter whether the other code is located inside or outside the try-finally construct, but that is not correct.
So if you want any run-time guarantees of correct behavior your first example is the only correct one.
In your first example, you acquire and more importantly use a connection (to a database, one would presume) inside the try block. If an exception occurs within the try block, then the finally block will execute and close your connection.
In your second example, your connection is acquired and used completely outside of the try-catch construct. If an exception occurs using the connection, it is likely that the whole context will just be tossed out, your finally block will not execute, and your connection will not be closed.
In your third example, finally is going to execute after try, but before any code that comes after the finally block. You will generate an exception trying to use the connection, because the connection has already been explicitly closed.

java.sql.SQLException: Exhausted Resultset

I am not getting how to solve this exception.
I am passing Resultset object to each thread.and doing some logic
My sample program is:
public class dataimport
{
public dataimport()
{
connect(); /*connect to database
}
private void connect()
{
try
{
/* connected data base
str="SELECT * FROM tablename where rownum<=5";
rs1 = statement.executeQuery(str);
while (rs1.next())
{
Runnable r = new MyThreadClass(rs1);
System.out.println(new Thread().getName());
new Thread(r).start();
}
}
Thread class
class MyThreadClass implements Runnable
{
public MyThreadClass(ResultSet rs1)
{
rs2=rs1;
}
public void run()
{
int i=1;
try
{
while (rs2.next())
{
date=rs2.getString("mydate");
System.out.println("mydate="+date);
}
}
catch (Exception ex)
{
ex.printStackTrace();
}
}
}
If i add while (rs2.next()) in thread class,there will be no exception,but mydate it will
print only two insight of few records.
please can any one help me on this.
thank you in advance
No way. You are getting concurrency errors.
You get N results -> start N threads. Inside each thread, you loop again over the resultset. It makes little sense, and worse, it can happen that one thread checks that rs.next is true, enter to iterate, get suspended by another thread that finish the result set data and, when resuming, tries to read data from a resultset with no data.
The simplest (without changing the mechanics) solution would be putting the threads main loop in a synchronized loop, but that will cause a massive deadlock so you will end with the same performance as no threads.
As for you code, I think that what you really want is, in the principal loop, extract all the results into a data structure, and pass that data structure to each thread so it can deal directly with it (and no passing a shared result set object which causes such problems).

Under which circumstance would this resource be leaking?

Eclipse 4 gives a warning which says the stmt may potentially not be closed and cause a resource leak:
class Test {
public void test() {
PreparedStatement stmt = null;
try {
stmt = HibernateSession.instance().connection().prepareStatement("");
} catch (final SQLException e) {
e.printStackTrace();
} finally {
if (stmt != null)
try {
stmt.close();
} catch (final SQLException e) {
e.printStackTrace();
}
}
}
}
Under which circumstance would that happen?
I guess the conclusion here is: this is an Eclipse bug?
A leak is possible if an exception is thrown when you call stmt.close() in the finally block.
The problem was that in your finally block an exception might potentially occur, which would prevent stmt from closing.
One workaround is that you can replace everything in the finally block with:
JDBCUtilities.close(stmt);
See the docs for JDBCUtilities.close. As you can see, no exception will be thrown using this utility method so you don't need to worry about resource leak. One additional benefit is that the utility method handles the null case for stmt as well so we don't need to code it ourselves.
Actually, it is good practice to use JDBCUtilities.
You need to be using Java 7's try with resources or a try-finally block:
try(stmt = HibernateSession.instance().connection().prepareStatement("")) {
}
This warning will be generated on types that inherit from AutoCloseable that are not guaranteed to be closed. (Or possible Closeable, I forget which).
Now that I see what you're asking, just write less complicated code.
Foo f = null; // don't do this, but it's what you're doing
f = new Foo();
Is what you're doing, and you found one of several situations where you actually have to pay a penalty for this extraneous work.
Furthermore your try/finally should be clean. .close() can't throw, why are you catching?
try { // don't do this
stmt.close();
}
catch(SQLException exc) {
}
Should generate an Eclipse warning telling you that you're catching something that doesn't throw. That might even be a compile error, not sure, but sounds like you would benefit from playing with Eclipse > Preferences > Compiler and reviewing what warnings are intelligent. If you don't understand a warning, google it and see if it would be helpful to you, don't just skip over it. (sort of like you did with this one).

Java try-finally construction

Could someone explain me some situation (example) when we can use this construction?
try{
//dangerous code here
} finally {
//always called
}
I really understand how it works but newer use in real situation.
Pretty much any time you have something like a Closeable, where you need to explicitly call close() to release the underlying resource, you want to put that call in a finally block, like:
FileReader f = whatever();
try {
// do some stuff with f
return;
}
finally {
f.close();
}
Even if no exception is thrown, and the return inside the try block is run, the resource will still be closed correctly.
try {
isWorking = true
//doStuff that might or might not succeed
} finally {
isWorking = false;
}
another example:
public void actionPressed()
{
if( isLoading )
return;
try {
isLoading= true;
doTheLoad);
} finally {
isLoading = false;
}
}
Some of the common scenarios:
Prevent resource leak:
Close IO streams and DB connections
Message logging
You might use it close database connections or any other resource - a file, hardware port, etc.
try{
// Do something I care about
} finally {
// Make sure we clean up, regardless of success or failure
}
Here's an example:
InputStream in = new FileInputStream(...);
try {
/ * use in here */
} finally {
in.close();
}
Basically, no matter what happens, in will always be closed. Without this, in could stay open until the garbage collector collects it (could be a long time). This is a problem because:
There is a limit on the number of files / network connections you can have open at once
Open network connections will continue to tie up resources on the remote end too (DB connections are a good example)
Closing an input stream also flushes it generally (flushing writes anything in the inputstream's buffer)
For instance when you read a file:
InputStream is = new FileInputStream("...");
try {
// do stuff
}
finally {
is.close();
}
This way your file is always closed, even if there is an exception.
openFile();
try {
int i = Integer.parseInt(someString);
String sub = someString.substring(2);
System.out.println(i+sub);
}
finally {
closeFile();
}
as you can see, there might several Exceptions be thrown during a code passage and you possibly don't want to catch every of them.
also there could an Error be thrown, which you should not catch!
in any way you want to close your file, before the method ends, so you put that in the finally-block
Look at this article, Java Exception Handling - Basics. Here described clearly about exception and where it is used.
This is a very common pattern:
InputStream stream = // acquire stream...
try {
// do stuff with stream that might throw...
}
finally {
IOUtils.closeQuietly(stream);
}
Note, IOUtils is a library from the Apache Commons project. You should always close the stream in a finally. closeQuietly eats any exceptions that might be thrown while trying to close the stream (which is OK because you can't do anything about it).
Especially we can use for data base connection close related code in finally block. if program throws any exception in this case DB connection will release .
This is example in JDBC.same can be applicable in session.close() in Hibernate.
try{
//dangerous code here
} catch(Exception e){
//Do some thing releted to your exception
} finally {
//close DB connection or close your hibernate session.
//always called
}
Well, let's say you open a connection to a database and make some queries. If a SQLException is raised by one of the queries, you're supposed to close the connection before doing something else. If no exception is raised, you're still supposed to close it.
So the try {} catch () {} is there to catch those SQLExceptions and do something about them, while the finally {} is there to close the connection in either case.
This would be a very common scenario, but the same is true with any resource that needs to be freed no matter what happens while using it.

May have a memory leak in Java webapp - have question about garbage collection and session attributes

I've been profiling my webapp locally on my pc with VisualVM. I'm pretty certain that I have a small memory leak. After taking a snapshot of the application, I chose the object that had the most instantiated objects and looked through the Allocation Call Tree to see if I could find which class (of mine) was contributing to the 'potential leak'.
I found three of my classes in the tree, and took a look at the method's that were pinpointed.
Here is a snippet of code (a method) from one of my servlets - this method gets the names of session attributes that I want to keep in the session and removes the rest.
public void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
conn = ds.getConnection();
stmt = conn.createStatement();
HttpSession session = req.getSession();
getExemptSessionAttributes(Customer_Number,rs,stmt,session);
}//try
catch (Exception e) { }
finally {
if (rs != null) {
try { rs.close(); } catch (SQLException e) { ; }
}
if (stmt != null) {
try { stmt.close(); } catch (SQLException e) { ; }
}
if (conn != null) {
try { conn.close(); } catch (SQLException e) { ; }
}
}//finally
}//post
public void getExemptSessionAttributes(int Customer_Number, ResultSet rs, Statement stmt, HttpSession session) {
try {
rs = stmt.executeQuery("Select Name from exemptsessionattributes");
String[] exemptAttributes = null;
int count = 0;
while(rs.next()) {
count++;
}
rs.beforeFirst();
exemptAttributes = new String[count];
count = 0;
while(rs.next()) {
exemptAttributes[count] = rs.getString(1);
count++;
}
session.setAttribute("ExemptSessionAttributes",exemptAttributes);
//garbage collect
exemptAttributes = null;
}//try
catch(Exception e) {}
}//end
//....
The only modification I've made thus far, since profiling my webapp, was the addition of setting the exemptAttributes[] object array to null.
My question is -
If a String array (or any object) is set into a session attribute, does that mean that the reference to that object, if not set to null in the code, is still 'referenced' and won't be garbage collected?
If a String array (or any object) is set into a session attribute, does that mean that the reference to that object, if not set to null in the code, is still 'referenced' and won't be garbage collected?
Not exactly.
If you have set an object as a session attribute, then that object will continue to be reachable (and not garbage collected) for as long as the Session object is reachable. The Session object is most likely cached in memory by the servlet infrastructure for a long time.
In this case, assigning null to the local variable does nothing useful. Firstly, the local is about to go out of scope anyway, and that has the same effect from a GC perspective. Secondly, you've just copied the object reference into a data structure (the Session object) that has a longer lifetime than the local variable ... so the object will continue to be reachable anyway.
In short, the object continues to be reachable irrespective of whether (or not) you assign null to the local variable.
Possible way to combat this "leak" include:
don't put a reference to the object into a session attribute,
set the session attribute to null, or
adjust the web container's session caching strategy so that idle sessions are dropped from the cache.
implement a scheme to invalidation sessions (e.g. log users out) after a period of idleness.
The scope of the exemptAttributes reference (not the actual object referenced by the reference) is the try block in your method. So the answer to your question seems to be a "No".
Could the leak be because you are not destroying the sessions? In other words, if you keep creating new sessions and setting exemptAttributes objects in these sessions, your memory usage will grow unless you are cleaning up old/unused sessions. (you can set a session timeout in web.xml)
To answer your actual question, no, nulling that reference is doing close to nothing. The variable is scoped only to that try {} block. It goes out of scope as soon as you leave the try and no reference is being held by this class any longer. There are very few 'real' cases where nulling a reference in a method does anything useful for garbage collection. It's going to stick around until the session releases its reference regardless.
The strange way ResultSet and Statement are being used, or simply not cleaning up old sessions, seem like better candidates for a problem.

Categories

Resources