Query regarding ResultSet - java

I am executing a Statement query and storing the data in ResultSet rs.
// if no record is returned by the query
if (!rs.next() ) {
Step1
}
// if atleast one record is returned by the query
if(rs.next()){
do {
if (rs.getString(1).equalsIgnoreCase("0")){
Step2
}
if (rs.getString(1).equalsIgnoreCase("1")){
Step3
}
} while (rs.next());
}
However if i am getting only a single record from the query then no steps are executed. It would be of great help if anyone can point out the mistake.

You have to understand what exactly next() method do. next() moves the cursor to next element. When you write next() inside if there the condition passed and there are no more elements when it comes to while.
And why don't you simplify your code by just doing
while ( rs.next() ) {
if (rs.getString(1).equalsIgnoreCase("0")){
Step2
}
if (rs.getString(1).equalsIgnoreCase("1")){
Step3
}
}
If you enter into while loop, there are items, otherwise No.

You are always skipping first element because you are calling .next() twice before taking an element.
Try doing something like this:
if (rs.next()) {
// At least one record returned
do {
if (rs.getString(1).equalsIgnoreCase("0")) {
// Step2
}
if (rs.getString(1).equalsIgnoreCase("1")) {
// Step3
}
} while (rs.next());
} else {
// No records returned
}

From JavaDoc ResultSet:
Moves the cursor froward one row from its current position. A ResultSet cursor is initially positioned before the first row; the first call to the method next makes the first row the current row; the second call makes the second row the current row, and so on.
In your code you don't need second invocation of rs.next() because cursor already on first row.

Initially rs contains one record or more precisely points to result set having one record.
Now when if(!rs.next()) is called then rs moves to the next record in result set which is not there as you have only one record. So this if goes well. But again when you use if(rs.next()) then rs won't be having any record, hence the if won't execute.

You should not call rs.next() method twice. Following logic should work:
if (!rs.next() ) {
Step1
}
else{ // if atleast one record is returned by the query
do {
if (rs.getString(1).equalsIgnoreCase("0")){
Step2
}
if (rs.getString(1).equalsIgnoreCase("1")){
Step3
}
}while (rs.next());
}

Related

Getting affected row count when there is no resultset object

I have given a pl/sql procedure that I am supposed to call from java code through jdbc.
public boolean deleteCompany(TimeStamp timestamp, Long companyId){
String str = "{call Delete_Company(?,?)}";
CallableStatement statement = null;
boolean deleted = false;
try{
statement = conn.prepareCall(str);
statement.setLong(1,companyId);
statement.setTimestamp(2,timeStamp);
statement.execute();
deleted = true;
return deleted;
}finally{
statement.close();
}
}
The problem is even if I send the wrong id number it obviously executes statement so varaible deleted becomes true. I tried .executeUpdate() method to be able to get affected row counts but it did not work properly cause when in both cases(when deletion/no deletion happened) it retrieved 1. I suppose the problem is the pl/sql procedure I am using just performs delete operation but not retrieve any result set object. So neither executeUpdate() nor getUpdateCount() methods does not help me. My question is there any way I can get affected row counts even if I have no result set object?
FYI: I understand that affected row count could be sent as a out parameter from pl/sql procedure, but I have no authority to make any change on the db side.
Since you can't change the stored procedure, one solution is to do the following
Get the number of rows before calling an update operation (select count(*) from your_tbl where .....)
Delete the records as you're already doing
Get the number of rows after the delete action and check if the number of affected rows is the same as in #1 (num_rows#1 - num_rows#3)
Other transactions can still make this approach somewhat unreliable because they can also change your table between steps #1 and #3.
If that's a concern for you, then you should use transactions (just place your Java code in a transaction).
Your statement.execute(); returns a boolean value and it always return true if the execution is success irrespective of what the procedure is doing on call. Further you can refer the below code for what you are looking.
...
boolean hadResults = cStmt.execute();
//
// Process all returned result sets
//
while (hadResults) {
ResultSet rs = cStmt.getResultSet();
// process result set
...
hadResults = cStmt.getMoreResults();
}
//
// Retrieve output parameters
//
// Connector/J supports both index-based and
// name-based retrieval
//
int outputValue = cStmt.getInt(2); // index-based
outputValue = cStmt.getInt("inOutParam"); // name-based
...

Getting all results from ResultSet

I am getting a ResultSet of type ArrayList<MyClass> and all is working well, except it's not getting the first item from the list.
It seems this part is actually taking the first option and using it, despite not actually doing anything with it:
if (!result.next()) {
//throw Excepion
}
Then after that I run the while (result.next()) { and populate the ArrayList.
The first item in the database is just an empty String (well a space actually), and there are n other entries. I want the blank entry there too because this fills a JComboBox and need the first entry to always remain as a blank option.
But, because of checking if (!result.next()) before the while (result.next()), it will only show from item2 onwards. If I remove the if, it will leave the blank option in the dropdown.
Just to note, this code is using a try...finally.
So my issues/queries are:
1) Would I be best off removing the if (!result.next()) and just putting in a catch for the same exception?
2) Is it possible to use the initial way I described, but keeping the first entry in the result?
3) Is there a better way to get the first entry than just having a space in the first entry in the table? (Note that if it's just literally blank, and I remove the if, it will show a tiny little option in the dropdown table.
Taking all items from ResultSet and placing them in a list goes like this:
List<MyObj> data = new ArrayList<>();
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT Id, Name, ...");
while (rs.next()) {
int id= rs.getInt("Id");
String name = rs.getString("Name");
data.add(new MyObject(id, name));
}
} catch (SQLException e ) {
JDBCTutorialUtilities.printSQLException(e);
} finally {
if (stmt != null) { stmt.close(); }
}
You do not need to check the state of rs, because the check in the header of the while loop is sufficient.
Oracle's reference
You can check this way:
if(!rs.isBeforeFirst())
rs.isBeforeFirst() returns false if the resultset contains no rows.
When you call the next() function you allways jump to the following record, you must avoid the if(!result.next()), you can use if(result != null) and then, the loop

Why does my SQL while(set.next()) skips the first element?

I execute:
select * from table_name order by column desc;
And I want to go through the items sequentially. I got the ResultSet from that and did:
while(set.next()) {
// processing code
}
Unfortunately, that skips the very first element. What's the best way to iterate through the entire ResultSet and include the very first element?
Use:
set.beforeFirst();
while(set.next()) {
// Your code
}
This will run the body of your loop once before advancing the ResultSet. You don't want to use a do loop (my previous answer) because it will throw an Exception if the query has 0 rows returned.
I know this is really old but my search hit here and after the solution didn't work for me (forward only result set) I believe the issue was never really addressed. In my case, I was doing:
jdbcTemplate.query(sql, rs -> {
while(rs.next()) {
// processRow
}
// no return statement
, args);
I then looked more closely at the method that was being called and the second argument was a "RowCallbackHandler" and not a "ResultSetExtractor" so the correct use of this code is:
jdbcTemplate.query(sql, rs -> {
// processRow
}, args);
This does the "while (rs.next())" loop for you.
I'd wager the OP was doing the same thing I was.
Your code is correct and you are not loosing any records. In the SDK Documentation for ResultSet you can read that:
"A ResultSet object maintains a cursor pointing to its current row of data. Initially the cursor is positioned before the first row. The next method moves the cursor to the next row, and because it returns false when there are no more rows in the ResultSet object, it can be used in a while loop to iterate through the result set."
Only case were you could loose records if you do a resultSet.next() before the one you are showing.
Whenever next() is called, it reads a record from result set.
if (!set.next() ) {
System.out.println("no data");
} else {
do {
//statement(s)
} while (resultSet.next());
}

null pointer exception can't be fixed

I'm implementing a software for a stock management system in java.I'm using MVC design pattern and i found this exception when trying to fill a JcomboBox. I want to get all the batches when a item-code is being passed into the method.so the method should return a array-list of relevant objects. but when I run this program it gave me this kinda error and it says there is empty result set. but i also tried the sql code manually in the terminal and it worked. so i can't imagine how to fix this error. i'm glad if anyone can tell me where is the problem. I tried to post my screen shots but it cannot be done as i don't have enough reputation
here is my code
String sql = "select batchNo from MainBatch where itemCode = ?";
Connection c=DBConnection.getInstance().getConnection();
PreparedStatement ps=c.prepareStatement(sql);
ps.setString(1, itemCode);
System.out.println(itemCode+" -----> item code is thiss");
ResultSet set=ps.executeQuery();
ArrayList<MainBatch> list=new ArrayList<>();
System.out.println(set.next()+" <-----result set is");
while (set.next()) {
MainBatch batch=new MainBatch(set.getString("batchNo"));
list.add(batch);
}
return list;
[
ResultSet.next() moves the result set's cursor to the next row. When you print it, before the while loop, you're losing the first row (or the only row in a single row result set). Personally, I'd just omit it, but if you have to have it, you could extract the result to a local variable:
boolean next = set.next();
System.out.println(next + " <-----result set is");
while (next) {
MainBatch batch=new MainBatch(set.getString("batchNo"));
list.add(batch);
next = set.next();
}
return list;
Remove this line.
System.out.println(set.next()+" <-----result set is");
You are calling set.next() twise, this moves the resultset pointer to next row.

Issues with JDBC navigation with resultSet.next();

My code belows doesnt work, just keep pointing the cursor at the first record, and when i try to replace the if statement with a while or for loop it just loops to the last record on my data table, when i click the button that performs the Action
Try {
string host="jdbc:derby://localhost:1527/Employees";
string uName="admin1";
string uPass="admin"
string SQL="SELECT * FROM Workers";
Connection con= DriverManager.getConnection(host, uName, uPass);
Statement stmt=Con.createStatement();
ResultSet=stmt.executeQuery(SQL);
if (rs.next())
{
string fname=rs.getString(first_name);
string lname=rs.getString(last_name):
txtFname.setText(fname);
txtLname.setText(lname);
}
else{
rs.previous();
//throw some sql error here}
}
catch(SQLException err) {
system.out.println(err.getMessage);
}
how do i get around this and get to a second, third,fourth to nth record successively (not simultaneously).
Looking at the ResultSet.next() doc, calling rs.next() once as an if condition will only move the cursor one position forward from its starting position. Hence, you only see the first record.
Replacing your if statement with either a while or for loop will cause the cursor to iterate through your entire result set. However, each iteration of the your current loop keeps overwriting the value of txtFname and txtLname with that of the "current" record. In order to capture the value of the 2nd, 3rd, 4th records etc... you will need to create a new TextComponent object at each iteration. For example,
// use some lists to capture intermediate records (for illustration only)
List<JTextComponent> allFnames = new ArrayList<JTextComponent>();
List<JTextComponent> allLnames = new ArrayList<JTextComponent>();
while(rs.next()) {
string fname=rs.getString(first_name);
string lname=rs.getString(last_name):
JTextComponent txtFname = new JTextComponent(); // new object
txtFname.setText(fname);
allFnames.add(txtFname);
JTextComponent txtLname = new JTextComponent(); // new object
txtLname.setText(lname);
allLnames.add(txtFname);
}
Now at the end of the while loop, the two lists will contain all your records.
javadoc says -
ResultSet#previous() -Moves the cursor to the previous row in this ResultSet
object.When a call to the previous method returns false, the cursor is positioned
before the first row. Any invocation of a ResultSet method which requires a
current row will result in a SQLException being thrown.
So in certain point of time your if(rs.next()) returns false then the else part executes and the cursor moves to the previous row in this ResultSet. Then When a call to the previous method returns false, the cursor is positioned before the first row. and then it will throw Exception
do it this way
if (!resultSet.next() ) {
System.out.println("resultset does not data");
} else {
do {
string fname=rs.getString(first_name);
string lname=rs.getString(last_name):
txtFname.setText(fname);
txtLname.setText(lname);
} while (resultSet.next());
}
One more thing check the comment of Nivedita and sort out the errors

Categories