When to close Statement when using jdbc - java

I am using odbc to connect mysql database in Java
I write a function "ExecuteQuery", it takes a string parameter as sql statement and returns its resultset. However, when should I close the statement object?
If I close it in function ExecuteQuery, the returned resultset will be closed as well.
If I don't close it, memory leak occurs as I do not have the reference of statement object in caller. Thank you

You're taking wrong approach. If you really need such function (which is doubtful), make it accept a Statement as a parameter and make a separate function to create and set up that statement. Then you may wrap your function and ResultSet work in a try..finally block and close the statement in finally.
E.g.
Statement statement = getStatement();
try {
ResultSet rs = executeQuery(statement, query);
...
} finally {
statement.close();
}
However, if you're facing such problems, you may want to re-consider your architecture. Take a look at Hibernate, for example.

Related

Statement and PreparedStatement in JDBC [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Difference between Statement and PreparedStatement
I have confused with Statement and PreparedStatement in JDBC.Is PreparedStatement is version of Statement? or any other difference in that ? Can any body clear that question. thanks.
From Using Prepared Statements of the Java official tutorials
Sometimes it is more convenient to use a PreparedStatement object for
sending SQL statements to the database. This special type of statement
is derived from the more general class, Statement, that you already
know.
If you want to execute a Statement object many times, it usually
reduces execution time to use a PreparedStatement object instead.
The main feature of a PreparedStatement object is that, unlike a
Statement object, it is given a SQL statement when it is created. The
advantage to this is that in most cases, this SQL statement is sent to
the DBMS right away, where it is compiled. As a result, the
PreparedStatement object contains not just a SQL statement, but a SQL
statement that has been precompiled. This means that when the
PreparedStatement is executed, the DBMS can just run the
PreparedStatement SQL statement without having to compile it first.
Although PreparedStatement objects can be used for SQL statements with
no parameters, you probably use them most often for SQL statements
that take parameters. The advantage of using SQL statements that take
parameters is that you can use the same statement and supply it with
different values each time you execute it. Examples of this are in the
following sections.

Can we execute some queries while traversing resultset in java

I am trying to implement a task in java using JDBC like Stored Procedure in SQL.
In SQL, when we write cursor, first we execute select query and then fetching the records we perform some actions.
Likely I have fired a select query in Hive.
sql="SELECT a,c,b FROM tbl_name";
res=stmt.executeQuery(); -----------> CONTAINS 30 RECORDS
while(res.next())
{
sql="INSERT INTO table .....";
rs1=stmt.executeQuery();
sql="SELECT d,e,f FROM table .....";
rs1=stmt.executeQuery();
like wise many queries are there.....
.
.
.
..
}
As my select query contains 30 records but when I execute it my while(res.next()) execute only once.
But instead of queries I just try to display field to check whether it is fetching or not
then it is working fine..
(while loop contains only System.out.println statements)
sql="SELECT * FROM tbl_name";
res=stmt.executeQuery(sql);
while(res.next())
{
S.O.P.("fields : "+res.getString(0));
}
(I think that when the resultset is getting traversed and if in between queries are there then queries get the executed but at the same time loop also get executes and after some time when queries execution get finishes by that while loop of resultset also get finishes and hence it get executes for once. I am not sure about it.)
Why it is happening I am not getting. Is anything I am doing wrong?
Each Statement can only have one open ResultSet at a time. From the documentation:
By default, only one ResultSet object per Statement object can be open
at the same time. Therefore, if the reading of one ResultSet object is
interleaved with the reading of another, each must have been generated
by different Statement objects. All execution methods in the Statement
interface implicitly close a statment's current ResultSet object if an
open one exists.
The calls to executeQuery inside your loop will implicitly close the outer ResultSet, so that's why you only see one row.
I would restructure your flow. Primarily, don't try and reuse the same Statement object to execute a new query. When I try that using the PostgreSQL driver, for example, I readily get an exception, "This ResultSet is closed."
Instead, rewrite it to something like this:
Connection conn = DriverManager.getConnection(...);
Statement outerStatement = conn.createStatement();
ResultSet outerResultSet = outerStatement.executeQuery("...");
while (outerResultSet.next()) {
Statement innerStatement = conn.createStatement();
ResultSet innerResultSet = innerStatement.executeQuery("...");
while (innerResultSet.next()) {
// ...
}
innerResultSet.close();
innerStatement.close();
}
outerResultSet.close();
outerStatement.close();
conn.close();
Of course, surround with try-catch-finally as needed.
It doesn't happen like that, You can try until your query gets executed loop will wait.
ideally you can only have one statement executing at one moment in time against one database connection so you can either create and execute the second statement, or iterate through the resultset from first statement and store the data in collection (e.g. in an arraylist of hashmap) then close that statement and run the second one, this time retrieving the id's from the collection you saved them in.

Little Confusion (ResultSets, OracleDB, JAVA)

I can successfully connect to an oracle database and print out the list of all table names using the getAllTableNames() method.
My next Idea is to filter specific tables and display all of their columns.
I am running this query at the moment (I am including the entire method.)
static void getLengths(){
String query = "SELECT column_name from user_tab_columns where table_name = '<MytableName>'"
try{
ResultSet rs = db.runQuery(query);
System.out.println(rs):
} catch (Exception ex) {
System.out.println(ex);
//Seems to be successful
}
} //End of Method
In the System.out Window I am receiving this which makes me think I just need to view my result set somehow?
oracle.jdbc.driver.DcrollableResultSet#(different number everytime I run code)
Is my result set hiding somewhere? What is the best way to go about viewing it?
System.out.println(rs) just prints out the class name and handle of the ResultSet object. This is pretty useless.
You need to loop through the result set and read the appropriate fields. Generally you write something like:
ResultSet rs=db.runQuery(query) // I don't know where this function is coming from, but okay
while (rs.next())
{
String myColumn=rs.getString("column_name");
System.out.println(myColumn);
}
rs.close();
You might want to read up on JDBC in general, and look at the Java Docs for Connection, Statement, and ResultSet.
You have to iterate over your ResultSet to get the values.
Do something like that
while(rs.next()) {System.out.println(rs.getString("COLUMN_NAME"));}
ResultSet javadoc states
A table of data representing a database result set, which is usually generated by executing a statement that queries the database.
So, you'll have to use the appropriate getXXX(int index) methods where XXX is your equivalent Java Datatype. And don't forget to invoke next() before doing anything else!
Read Retrieving and Modifying Values from Result Sets to see an example of what you're trying to accomplish.
You will need to step through the result set, very rusty on my java, but you can probably call "toString()" on the resultset to at least show you what was returned although its not going to be very usable.
System.out.println(rs.toString())

One Statement object, multiple executeUpdates

Is recommended to create just one Statement object and execute multiple executeUpdate() on it?
// Vantages/drawbacks of this solution?
conn.setAutocommit(false);
Statement stmt = conn.createStatement();
stmt.executeUpdate('[ANY_INSERT_SQL]');
stmt.executeUpdate('[ANY_INSERT_SQL]');
stmt.executeUpdate('[ANY_INSERT_SQL]');
conn.commit();
Or is better one Statement object for each executeUpdate:
// Vantages/drawbacks of this solution?
conn.setAutocommit(false);
Statement stmt1 = conn.createStatement();
stmt1.executeUpdate('[ANY_INSERT_SQL]');
Statement stmt2 = conn.createStatement();
stmt2.executeUpdate('[ANY_INSERT_SQL]');
Statement stmt3 = conn.createStatement();
stmt3.executeUpdate('[ANY_INSERT_SQL]');
conn.commit();
Thanks in advance.
PS: I know PreparedStatement class and I use it often, but my doubt is about Statement usage.
It doesn't matter, just make sure you close all statement objects.
Based on the javadoc, A statement can have only one associated ResultSet object.
The object used for executing a static
SQL statement and returning the
results it produces.
By default, only one ResultSet object
per Statement object can be open at
the same time. Therefore, if the
reading of one ResultSet object is
interleaved with the reading of
another, each must have been generated
by different Statement objects. All
execution methods in the Statement
interface implicitly close a
statment's current ResultSet object if
an open one exists.
http://download.oracle.com/javase/1.4.2/docs/api/java/sql/Statement.html
If you need to process multiple results sets at the same time, perhaps, more statements make sense.
Probably more often than not, you only need to use one.
Performance-wise, probably better as it keeps fewer resources active.

What happens to the original resultSet when it is returned from a method into a new object?

pseudo code to explain my self better. I'm learning Java at this point in time.
if I have a method
public resultSet getEverything()
{
resultSet rs = blabla;
return rs
}
I can't rs.close() as I need to use it in the method I retrieve it
hence then I will use it, and maybe 'close' the new resultSet I create.
What happens from the previous resultSet?
Is it left to be collected by the garbage collector?
Does it close itself when I close the 'new' resultSet?
Does it have any impact on code efficiency/performance?
Any feedback would be greatly appreciated :) as this has confused me a bit. It is more of an OOP question rather than Java I think.
Thanks!
You should not be returning a java.sql.ResultSet from a method. It should always be created, mapping into an object or data structure, and closed in the scope of the method in which it was created in a finally block.
A java.sql.ResultSet is associated with a database cursor, a scarce resource. You don't want to keep those open for a long time.
Garbage collectors do not clean up result sets, statements, or connections to databases. It will remove the reference from memory, but the cursor or connection will still be open on the database side. It's your responsibility to close them properly or you'll exhaust the supply.
An object, data structure, or CachedRowSet is the right thing to return.
There's only one resultSet here. You create it and return it in this method; the calling method (the one that calls getEverything()) now has it - it doesn't have a copy, or anything like that; it has the resultSet you create in this method. But the calling method must assign the result of getEverything() if it is to close it - like this:
resultSet rs = getEverything();
versus simply calling the method like this:
getEverything();
In the second case, the result set would be created, then made available to the behind-the-scenes garbage collector (essentially, deleted) without an opportunity to close it.

Categories

Resources