In a few answers here on SO there is recommended to use ResultSet's function getRow() in order to get the number of entries in a query result. However, following code
private static int getSizeOfResultSet(ResultSet result) throws SQLException{
if(result != null){
int count = 0;
while(result.next()){
count++;
}
System.out.println("Count of resultset is " + result.getRow() + " and count " + count);
return result.getRow();
}else{
System.out.println("Result is null");
return 0;
}
}
is returning me things like
Count of resultset is 0 and count 1
when there is assured that entries are existing (in a JUnit test case). Note that this project has to be in Java6-standard, so maybe this is the issue. Is there anything to consider using the getRow() function?
Additionally, I tried with
result.last();
int c = result.getRow();
result.beforeFirst();
return c;
like mentioned here, but the result is still 0.
EDIT: I should mention that the while(result.next())-loop is for testing purpose. The behaviour without the loop is exactly the same (i.e. 0).
The javadoc states
returns the current row number; 0 if there is no current row
After you've visited all the rows with ResultSet#next() there is no current row.
Use your count value for the number of rows. Or use a SELECT count(*) ... style query.
Related
Here is my MySql table:
I want to show the output of the query in commandline as below:
I have written the code below to loop but I am getting only the first row, What i have to modify ??
ResultSet rs2 = stmt.executeQuery(table_retrive);
String[] cols = new String[itemList.size()];
int[] rec =new int[itemList.size()];
for (int i = 0; i < itemList.size(); i++) {
while (rs2.next()) {
cols[i] =(String) itemList.get(i);
rec[i] = rs2.getInt(cols[i]);
System.out.println(rec[i]+" ");
}
}
Your two loops are wrong. Start at i=0 and then iterate once over the whole ResultSet, filling yor first array position. When this is done, i is incremented and you try to iterate the ResultSet a second time but the cursor is at the end of the ResultSet, so rs2.next() returns false and the code will not be executed.
So you have two Solutions:
Handle the loops correctly. Unfortunately I do not know, what you are trying to do anyways because this is some C-like code without OOP, which doesn't show semantics and then you have this itemList which seems to hold preset values and you read out of this list, which column to take for the i-th position. This seems odd. Maybe switching the loops does the desired: Start with the while and nest the for.
Reset the cursor of the ResultSet after the while with rs2.beforeFirst(). WARNING: This could throw a SQLFeatureNotSupportedException. Not all Databases can move the cursor backwards. This is of course a very ugly solution, since you should first parse the whole row a once.
Try to use printf() Or format() method. It is same as printf method in c lang. you can pass parameters and difference. Look at link1
And link 2
Example : System.out.printf("%d%5s%10d", 5,"|",10);
output : 5 | 10
Using this the I got all the values but in one row :
while (rs2.next()) {
for (int i = 0; i < itemList.size(); i++) {
cols[i] =(String) itemList.get(i);
rec[i] = rs2.getInt(cols[i]);
System.out.print(rec[i]+" ");
}
}
But I need to divide like the rows.
Usage of the inner loop is your problem.
You can enhance your code to remove the usage of the second loop in your code, it basically does nothing. You can loop over your result set and in the same loop using the incremented variable to persist the values accordingly.
The code shown half implemented in your question, hence it will be difficult to give you exactly what need to be done. Nevertheless, here's an attempt to resolve the problem for you:
while (rs2.next()) {
System.out.println(rs2.getInt(1) + "\t |" + rs2.getString(2) + "\t |" + rs2.getString(3));
}
Based on the column names from the table in the question, assuming that column2 and column3 are String's.
You can add the necessary details to this code to complete it according to your usecase, but I've just taken the example of showing a record in one line.
EDIT:
OP has his own way of programming, but to satisfy his question in the comment - this is how you can do it.
while (rs2.next()) {
for (int i = 0; i < itemList.size(); i++)
{
cols[i] =(String) itemList.get(i);
rec[i] = rs2.getInt(cols[i]);
System.out.print(rec[i]+"\t |");
}
System.out.println();
}
I was trying to understand how PagingState works with Statement in Cassandra. I tried with a sample that inserts few 1000s of records into database and tried reading the same from DB with fetch size set to 10 and using paging state. This is working perfectly fine. Here is my sample junit code:
#Before
public void setup() {
cassandraTemplate.executeQuery("create table if not exists pagesample(a int, b int, c int, primary key(a,b))");
String insertQuery = "insert into pagesample(a,b,c) values(?,?,?)";
PreparedStatement insertStmt = cassandraTemplate.getConnection().prepareStatement(insertQuery);
for(int i=0; i < 5; i++){
for(int j=100; j<1000; j++){
cassandraTemplate.executeQuery(insertStmt, new Object[]{i, j, RandomUtils.nextInt()});
}
}
}
#Test
public void testPagination() {
String selectQuery = "select * from pagesample where a=?";
String pagingStateStr = null;
for(int run=0; run<90; run++){
ResultSet resultSet = selectRows(selectQuery, 10, pagingStateStr, 1);
int fetchedCount = resultSet.getAvailableWithoutFetching();
System.out.println(run+". Fetched size: "+fetchedCount);
for(Row row : resultSet){
System.out.print(row.getInt("b")+", ");
if(--fetchedCount == 0){
break;
}
}
System.out.println();
PagingState pagingState = resultSet.getExecutionInfo().getPagingState();
pagingStateStr = pagingState.toString();
}
}
public ResultSet selectRows(String cql, int fetchSize, String pagingState, Object... bindings){
SimpleStatement simpleStatement = new SimpleStatement(cql, bindings);
statement.setFetchSize(fetchSize);
if(StringUtils.isNotEmpty(pagingState)){
statement.setPagingState(PagingState.fromString(pagingState));
}
return getSession().execute(simpleStatement);
}
When I execute this program, I see that every iteration in testPagination is exactly printing 10 records. But here is what the documentation says:
Note that setting a fetch size doesn’t mean that Cassandra will
always return the exact number of rows, it is possible that it
returns slightly more or less results.
I am not really able to understand why Cassandra will return not exactly the same number of rows as specified in fetch size. Is this the case when there is no where clause provided in the query? Will it return exact number of records when a query is constrained on a partition key? Please clarify.
From the CQL protocol specification:
Clients should also not assert that no result will have more than result_page_size results. While the current implementation always respect the exact value of result_page_size, we reserve ourselves the right to return slightly smaller or bigger pages in the future for performance reasons
So it's good practice to always rely on getAvailableWithoutFetching instead of the page size, in case Cassandra changes its implementation in the future.
I use the below approach to determine my result set is not empty and proceed to do assertions on the values.
...
resultSet = statement.executeQuery("select count(*) as rowCount from tbName where...");
while (resultSet.next()) {
rowCount = Integer.parseInt(resultSet.getString("rowCount"));
}
Assert.assertTrue(rowCount > 0);
resultSet = statement.executeQuery("select * from tbName where ...");
while (resultSet.next()) {
//do some assertions on values here.
}
...
Is there anyway to get the number of rows directly from the resultSet directly in a single query? Something like the below?
resultSet = statement.executeQuery("select * from tbName where ...");
if( resultSet.count/length/size > 0) {
}
You can change the query to include a column with the row count:
select t.*, count(*) over () as row_count
from tbName t
where ...
then you can get the count using
int rowCount rs.getInt("row_count");
Note that you won't get a 0 count because that means the actual query did not return anything in the first place. So you can't use that to verify if your query returned anything. If you only want to check if the result is empty, use next()
resultSet = statement.executeQuery(".....");
if (resultSet.next()) {
// at least one row returned
} else {
// no rows returned at all
}
Btw: you should always use the getXXX() method that matches the column's data type. Using getString() on all columns is not a good idea.
1) Moves the cursor to the last row: resultset.last();
2)Retrieves the current row number: int count = resultset.getRow();
Tips:
It's based on you create a statement via calling function "
Statement createStatement(int resultSetType,int resultSetConcurrency)
throws SQLException"
to gernerate a scrollable resultSet.
There are two ways to get number of rows.
1) if you want to check the number of rows exist in table you may use count query.
2) if you want to count number of rows in a result set you have to traverse that result set to count rows.
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();
}
}
I want to get the size of the ResultSet inside the while loop.
Tried the code below, and I got the results that I want. But it seems to be messing up with result.next() and the while loop only loops once if I do this.
What's the proper way of doing this?
result.first();
while (result.next()){
System.out.println(result.getString(2));
System.out.println("A. " + result.getString(5) + "\n" + "B. " + result.getString(6) + "\n" + "C. " + result.getString(7) + "\n" + "D. " + result.getString(8));
System.out.println("Answer: ");
answer = inputquiz.next();
result.last();
if (answer.equals(result.getString(10))) {
score++;
System.out.println(score + "/" + result.getRow());
} else {
System.out.println(score + "/" + result.getRow());
}
}
What's the proper way of doing this?
Map it to a List<Entity>. Since your code is far from self-documenting (you're using indexes instead of column names), I can't give a well suited example. So I'll take a Person as example.
First create a javabean class representing whatever a single row contains.
public class Person {
private Long id;
private String firstName;
private String lastName;
private Date dateOfBirth;
// Add/generate c'tors/getters/setters/equals/hashcode and other boilerplate.
}
(a bit decent IDE like Eclipse can autogenerate them)
Then let JDBC do the following job.
List<Person> persons = new ArrayList<Person>();
while (resultSet.next()) {
Person person = new Person();
person.setId(resultSet.getLong("id"));
person.setFirstName(resultSet.getString("fistName"));
person.setLastName(resultSet.getString("lastName"));
person.setDataOfBirth(resultSet.getDate("dateOfBirth"));
persons.add(person);
}
// Close resultSet/statement/connection in finally block.
return persons;
Then you can just do
int size = persons.size();
And then to substitute your code example
for (int i = 0; i < persons.size(); i++) {
Person person = persons.get(i);
System.out.println(person.getFirstName());
int size = persons.size(); // Do with it whatever you want.
}
See also:
How to check if there is zero-or-one result or one-or-more results and their size
you could do result.last(); and call result.getRow(); (which retrieves the current row number) to get count. but it'll have load the all the rows and if it's a big result set, it might not be very efficient. The best way to go about is to do a SELECT COUNT(*) on you query and get the count like it's demonstrated in this post, beforehand.
This is a tricky question.
Normally, result.last() scrolls to the end of the ResultSet, and you can't go back.
If you created the statement using one of the createStatement or prepareStatement methods with a "resultSetType" parameter, and you've set the parameter to ResultSet.TYPE_SCROLL_INSENSITIVE or ResultSet.TYPE_SCROLL_SENSITIVE, then you can scroll the ResultSet using first() or relative() or some other methods.
However, I'm not sure if all databases / JDBC drivers support scrollable result sets, and there are likely to be performance implications in doing this. (A scrollable result set implies that either the database or the JVM needs to buffer the entire resultset somewhere ... or recalculate it ... and that's expensive for a large resultset.)
The way of getting size of ResultSet, No need of using ArrayList etc
int size =0;
if (rs != null)
{
rs.beforeFirst();
rs.last();
size = rs.getRow();
}
Now You will get size, And if you want print the ResultSet, before printing use following line of code too,
rs.beforeFirst();
There are also another way to get the count from DB.
Note :
This column gets updated when DBA'S do realtime statistics
select num_rows from all_Tables where table_name ='<TABLE_NAME>';