Little Confusion (ResultSets, OracleDB, JAVA) - 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())

Related

Why does my while loop only go through one name in the database, instead of all of them? my program should sum values assigned to the same name

String name;
int sum;
myRs = myStmt.executeQuery("SELECT DISTINCT person FROM Todo_tbl");
while (myRs.next()) {
name = myRs.getString("person");
System.out.println(name);
sum = 0;
ResultSet myRs2 = myStmt.executeQuery("SELECT duration FROM Todo_tbl WHERE person ='" + name + "' ");
while (myRs2.next()) {
sum += (int) myRs2.getInt("duration");
JList<Integer> list2 = new JList<>();
}
dfduration.addElement(sum);
}
That is the code I use, the problem is that the loop only goes through one name and closes after. I am not sure why, the code is supposed to go through all the names in the database and sum the values assigned to the same name.
I will be so grateful for any help!
You are attempting to use two ResultSets generated by the same Statement in interleaving fashion. This will not work. As the API docs for java.sql.Statement put it:
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 current ResultSet object of the statement
if an open one exists.
Thus, as soon as you perform the myStmt.executeQuery() inside the inner loop, the ResultSet to which myRs refers is closed. The next call to myRs.next() therefore returns false, and no further loop iterations are performed.
I suggest a different query:
SELECT person, duration FROM Todo_tbl ORDER BY person
Then use a single loop over the results. Aside from not requiring multiple Statements, it would use only one query, which is much more efficient.
Alternatively, leave out the ORDER BY clause, and perform the grouping by person on the Java side, with the help of a Map.
On the other hand, if all you want to do is get the sum of all of each person's durations (the code presented does nothing else, but maybe you want the individual points for some purpose not reflected in the question) then the best alternative would probably be to make the database do the work:
SELECT person, SUM(duration) as total_duration FROM Todo_tbl GROUP BY person
Any way around, details of how to write the appropriate loop for handling those results are left as an exercise.

PreparedStatement parameter index out of range

I am getting a parameter index out of range error when executing a prepared statement. I have several other statements working correctly. The only difference with this query is it's the only UPDATE. The rest are all INSERT, ADD, DELETE etc. Any guidance on what I may be doing wrong would be greatly appreciated.
sqlStatement = "UPDATE customer SET customerName = ?, addressId = ? WHERE customerId = ?;";
StatementHandler.setPreparedStatement(ConnectionHandler.connection, sqlStatement);
StatementHandler.getPreparedStatement().setString(1, name);
StatementHandler.getPreparedStatement().setInt(2, AddressDAO.getAddressId(address));
StatementHandler.getPreparedStatement().setInt(3, customerId);
StatementHandler.getPreparedStatement().executeUpdate();
Error:
java.sql.SQLException: Parameter index out of range (3 > number of parameters, which is 1).
I have put a couple print statement sin the middle of the code block and it seems to fail on the 3rd parameter. All values coming in are valid and match the types being assigned. MySQL is being used and the statement works fine if executed in the console.
Thank you for reading and any help you can provide.
Edit: Here is the statement handler method I am using as well. I am combing through to see what else I should add to help get this thing figured out. Thank you for the comments!
public class StatementHandler {
/**
* create statement reference
*/
private static PreparedStatement preparedStatement;
/**
* method to create statement object
*/
public static void setPreparedStatement(Connection connection, String sqlStatement) throws SQLException {
preparedStatement = connection.prepareStatement(sqlStatement);
}
/**
* getter to return statement object
*/
public static PreparedStatement getPreparedStatement(){
return preparedStatement;
}
}
Your snippet doesn't make it clear, but I can guess. I'll list a series of conclusions I'm drawing; you'd have to doublecheck these:
StatementHandler is a class (not a variable). (reason: You've capitalized it).
setPreparedStatement and getPreparedStatement are static methods in the StatementHandler class. (follows naturally).
You are using multiple threads (reason: That would be sufficient to explain this problem).
You aren't synchronizing (reason: Same as #3).
Then this result is obvious: You can't do that. Your entire VM has one global 'prepared statement' with multiple threads calling setPreparedStatement and getPreparedStatement in more or less arbitrary orders. One thread calls setPreparedStatement, then another thread does, then the first tries to get the prepared statement the other one set, and it all goes to hades in a handbasket.
You can't do it this way. Heck, you can't even share a connection between two threads (as they'd be getting in each other's way and messing up your transactions).
If you don't quite get what static does (And it is, admittedly, a bit of an advanced topic), don't ever use it. You can pretty much write all the java you'd ever want without using static methods. The one exception is public static void main which must be static, but just make that the one-liner: new MyClass().go();, with go() being a non-static method, and you're good to go.
I'd like to go one step further than rzwitserloot and presume that your AddressDAO uses StatementHandler, too.
The query for AddressDAO.getAddressId(address) has probably one parameter, which matches the 1 from the Exception, and replaces the prepredStatemt before setting the third parameter.
As proof it would be suffient assigning AddressDAO.getAddressId(address) to a variable(and use it afterwards) before setting the prepared statement.
Alternativly you can get once the prepared statement in a variable and use this variable afterwards.

Oracle connection preparedStatement object print out the query to be executed

In Java I would want to print out the query that is going to be submitted/queried on the database so that I can see whats the error when the query throws out exception.
It will be useful to exactly locate the issue instead of trying to understand Oracle Exception ID's and trying to match where exactly did it fail in the code. Any help please.
PreparedStatement ps = conn.prepareStatement("SELECT * FROM EMPLOYEES where EMPNAME=?");
ps.setString(1, "HULK");
ps.executeQuery();
Ideally I want to do a syso(ps) or syso(ps.getquery) and the output should be
SELECT * FROM EMPLOYEES WHERE EMPNAME='HULK'
or
SELECT * FROM EMPLOYEES WHERE EMPNAME=<HASHCODE OF THE OBJECT YOU ARE TRYING TO BIND>
Something interesting I ran across, Log4JDBC, which allows you to log SQL Calls. I haven't had a chance to use it yet, but I thought it was a great idea to be able to change the logging level and get the SQL calls into a log file.
This is more than you asked for, but I thought it might be worth throwing out there.
I think this is already been answered here.
Short answer: print toString() method or the PrepareStatement to see the query with the bind variables substituted with values.
BUT: It al depends of the implementor. Not all JDBC drivers add this nicety.
If your particular driver doesn't comply with this, then the only workaround would be composing the SQL by concatenating the values instead of using bind variables (losing the performance advantages the RDBMS gives you when using bind variables).
But for this you have to convert things to strings, etc.
This would be paradoxical, since I have found that concatenated SQLs are the most error prone and are the ones that need most printing and checking.

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.

When to close Statement when using jdbc

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.

Categories

Resources