Not validating result set size using Java - java

This is a weird issue. I know I'm making a small mistake but not able to figure it out what exactly in it.
I'm executing one query and it has result set. First I'm validating if it doesn't has records then set one of the DTO attribute to false. If it has records, then iterate and do some business.
rs = partyPreparedStatement.executeQuery();
if(!rs.next()) { // It has records, but I'm checking with ! operator to make sure it goes to false or true.
purchaseDto.setPOIssued(false);
} else {
while (rs.next()) { // It has records, but still its not going to execute business
// Do some business here.
break;
}
}
Is the design correct?

If data is returned you will be ignoring the first row.
The first call to next() will already position the ResultSet to the first row (if there is data). But you don't do anything with that row, you immediately call next() again (in the while condition) thus ignoring the first row completely.
How you solve this problem is a matter of taste. I personally would simply count the number of rows processed:
If you only want to process the first row, you don't need a while to begin with:
rs = partyPreparedStatement.executeQuery();
if (rs.next()) {
purchaseDto.setPOIssued(true);
// process the data here
} else {
purchaseDto.setPOIssued(false);
}

You move the cursor two times so instead you can use do{}while loop :
if (!rs.next()) {
purchaseDto.setPOIssued(false);
} else {
do {
// Do some business here.
break;
} while (rs.next());
}

set the value default to false and in the loop to true
purchaseDto.setPOIssued(false);
while (rs.next()) { // It has records, but still its not going to execute business
// Do some business here.
purchaseDto.setPOIssued(true);
break;
}

Related

Difference between assigning a boolean variable a value and assigning a result of a comparison in Java

My collegues passed me some code, and there are problems when I run the code. Here is some part of it
boolean purchased = false;
conn = DriverManager.getConnection(connectionUrl, connectionUser, connectionPassword);
stmt = conn.createStatement();
String sql = new StringBuilder().... // some query
rs = stmt.executeQuery(sql);
while (rs.next()) {
//some code
purchased = rs.getInt("purchased") == 1;
print(" purchased:" + purchased);
}
This always printed purchased as false. I changed that part to this:
while (rs.next()) {
//some code
if(rs.getInt("purchased") == 1) purchased = true;
print(" purchased:" + purchased);
}
Now it works perfectly.
note: my ResultSet can have only 1 record. And in DB purchased is bit type, so there can be no other values than 0/1.
What is the difference between those two ways of writing ? as I know both should work the same way.
What is the difference between those two ways of writing ? as I know both should work the same way.
No, definitely not. In your first piece of code, if rs.getInt("purchased") returns a value other than 1, you assign a value of false.
In your second piece of code, once purchased has been set to true, it stays true for the rest of the loop.
So suppose your first row has a value of 1 for purchased, and your second row has a value of 2, then in your first piece of code the variable will become true then false, but in your second piece of code the variable will be set to true in the first iteration and then not changed in the second iteration.
Actually it's this code that's equivalent to your colleague's code:
while (rs.next()) {
// some code
if(rs.getInt("purchased") == 1)
purchased = true;
else purchased = false;
print(" purchased:" + purchased);
}
Now they'll behave the same since purchased is not set to true forever once it's set.
The difference is that once the variable becomes true you are never changing it to false. You need to determine which is correct, based on the contract of the method, or the expected behaviour.
It doesn't seem at all likely that your version is correct.
How many records are in ResultSet and corresponding values?
It would not have made a difference without while loop ( if first record returns value as 1 ) or if ResultSet has only one record with value as 1.
while loop in first code might be setting false value in second iteration or so. So at the exit time of while loop, purchased value being carried is false. In second way, you are setting purchased value to true when value is 1 and that is not again getting reset to false ( because purchased value is not getting reset for other rows of ResultSet).
Hope it helps !!
I agree with Jon Skeet that in your first answer the value changes on each iteration of the while loop, but in the second piece of code the value of the boolean variable does not change every time.
I don't know your requirement but I think you should also add the else part in code as well to change the boolean the value of rs.getInt("purchased") other than 1 , as in your existing code you only make the boolean variable true.

Is it safe to delete rows from Android SQLite database while iterating cursor

For example:
public void removeStaleMovies(Set<String> updatedMovieList) {
Cursor cur = this.getReadableDatabase().rawQuery("SELECT id, title, year FROM movie", null);
cur.moveToFirst();
while (!cur.isAfterLast()) {
String title = cur.getString(1);
String year = cur.getString(2);
if (!updatedMovieList.contains(title + "-" + year)) {
// delete the row where 'id' = cur.getString(0)
// OR, delete the row using the object at the cursor's current position, if that's possible
// OR, if deletion isn't safe while iterating, build up a list of row id's and run a DELETE statement after iteration is finished
}
}
}
Is deletion safe to do? Or can it result in some unpredictable behavior? I am aware of this similar question, but I'm still unsure.
From a code safety standpoint, this should be OK, assuming that the result set of your query is less than 1MB. In that case, the Cursor holds in heap space the entire result set, so it is insulated from any changes to the underlying database.
That being said, you may want to build up a list of rows to delete, simply so you can delete them in a single statement, rather than a bunch of individual statements (though wrapping those individual statements in a transaction may give you similar performance characteristics).

Function works only with hard coded values

This is the code I am working on:
if(connection.doDatabaseRead(findSQL))
{
ResultSet retRES = connection.getResultSet();
int i = 0;
// did we find anything
while( retRES.next() )
{
//read result from query
suiteNum.add(retRES.getString(i)); // this is the problem
i++;
//let other threads breathe
Thread.yield();
}
}
suiteNum is a string vector
When I try to add the database results to the vector the code crashes with this error.
java.sql.SQLException: Column Index out of range, 0 > 1.
I have the same piece of code working elsewhere in the program but I use real numbers like 0, 1 and 2 instead of i and it works fine.
As I do not know how many results the database request will have I need it to be dynamic but it will only work hard coded.
How can I make it work with i ?
The argument to getString is the column index, not the row index as you seem to think. The function returns the value of the given column in the current row, while next advances the cursor to the next row.
You probably mean:
suiteNum.add(retRES.getString(1));
in which case you can lose i altogether.
Java ResultSet objects are 1-indexed in this regard. The first element is at 1, not 0. See the javadoc.
EDIT: That's true too, but indeed the problem is this appears to be used as a row index! it's certainly the column.
This is your problem:
i = 0;
...
retRES.getString(i);
ResultSet.getString(i) gets a String from column number i
You want something like
while(retRes.next()) {
add(retRes.getString(1);
}
column index starts from 1
As I do not know how many results the database request will have I need it to be dynamic but it will only work hard coded. How can I make it work with i
ResultSetMetaData rsMetaData = rs.getMetaData();
int numberOfColumns = rsMetaData.getColumnCount();
See Also
ResultSetMetaData
Let your i start with 1 as specified in the API docs
if(connection.doDatabaseRead(findSQL))
{
ResultSet retRES = connection.getResultSet();
int i = 1;
// did we find anything
while( retRES.next() )
{
//read result from query
suiteNum.add(retRES.getString(i)); // this is the problem
i++;
//let other threads breathe
Thread.yield();
}
}

How to check if resultset has records returned w/o moving the cursor in Java

I am wondering how to check if the resultset has some records returned, just like below,
while(((ResultSet) rs).next()){
((ResultSet) rs).previous();
return true;
}
But I can't do this since the result set type is TYPE_FORWARD_ONLY, is there any handy API available for my case? wasNull is not the right one for certain, thank you for any pointers!
Even
if(!resultSet.isBeforeFirst()){
System.out.println("resultset contin no rows");
}
isBeforeFirst() returns true if the cursor is before the first row; false if the cursor is at any other position or the result set contains no rows
The answer is, you can't. That the nature of SQL row sets: You are notified when you hit the end, but you don't know until you try to get the next record and there isn't one. It's just the way it is.
Since you can not know before you make the rs.next() move about the state of your ResultSet you could probably:
run a count statement before your create your ResultSet or
do a first rs.next(), or rs.first() and use its contents in case your set is not empty like
this:
boolean state = rs.first(); // or rs.next();
if (state == false)
System.out.println("empty");
else {
System.out.println("not empty");
while (state) {
System.out.println(rs.getInt(1));
// use your row ...
state = rs.next();
}
}
If your first call to rs.next() is successful and it returned true, that means there are some records returned.

problem with Recordset

rs = ldao.getLonaAllList(schemeName, memid, TStrCalcdt);
if(!rs.next())
{
MessageBox mb = new MessageBox(sh, SWT.ICON_INFORMATION);
mb.setMessage("No Data Found");
mb.open()
return;
}
while (rs.next()) {
//other code for bringing the dat
}
i want to check, if the record doesnot contain the data then it shows the message. but i found the problem that while getting the record in every case, the first recordset data is not displayed.
so please can any body help on this. how can i show that the record set does not contain any data without losing my first data in dataset
Since rs.next() already moves to the next record and you call it twice before you enter the loop body, it is clear that the first record gets skipped. Replace your while loop with a do-while:
do {
//other code for bringing the dat
} while (rs.next());
(All of this assumes you're actually talking about a ResultSet or something with a similar interface).

Categories

Resources