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();
}
}
Related
I have a list of query parameter in my url that I want to use them in my java web service to run a query on a table
public Set<Result> getResult(String query, List<String> sortedQueryParamsValue) {
Connection connection = getConnection();//jdbc connection
//query is some thing like: select * from table A where status = ? and Id = ?
try (PreparedStatement getStatement = connection.prepareStatement(query)) {
for (int i = 0; i <sortedQueryParamKeys.size(); i++) {// sortedQueryParamsValue length is matching the number of values I need for the query and the order matches the order I am expecting
String value = sortedQueryParamsValue.get(i);
getStatement.setString(1, value);
}
try (ResultSet rs = getStatement.executeQuery()) {
while (rs.next()) {
//add to the list of results
}
}
//return the resultset
}
The reason that I used 1 always in getStatement.setString(1, value); is that I thought in each iteration one ? is replaced with the value, but at the end I get some exception back saying java.sql.SQLException: IN or OUT param missing at position 2.
Does anyone knows what I am doing wrong in here?
You can't use 1 every time in getStatement.setString(). You have to increment that number too in order to replace second ? with an actual value.
Since you are only passing 1 all the time and then trying to execute the query, Java is saying that there is no value provided for the second ? when you get java.sql.SQLException: IN or OUT param missing at position 2.
Replacing getStatement.setString(1, value) with getStatement.setString(i+1, value) should do the trick. But you'll have to ensure that the number of elements in sortedQueryParamsValue is equal to the number of ? in your getStatement query.
EDIT: Corrected setString(i,value) to setString(i+1,value) after #Eritrean's comment.
The problem was that passing query parameter through URL to the rest API can have some white spaces and those white spaces causes the query to return empty,
I am going to change 1 to i+1 just to not causing misleading readers
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 have the following problem:
I need to set a boolean true is an entry in a database exists.
ResultSet rc1 = null;
int Counterval;
String url = "jdbc:db2://localhost:50000/dbname";
Connection conn = DriverManager.getConnection(url,"","");
Statement st = conn.createStatement();
String sqlmd="select count(*) as Counter from tablename where mdsum = '"+mdSum+"' and filename = '"+Filename+"'";
rc1=st.executeQuery(sqlmd);
Counterval=rc1.getInt("Counter");
System.out.println("VAL: "+Counterval);
conn.close();
I get the following error message:
[jcc][t4][1090][10899][4.19.26] Illigal operation to read at the current cursor position. ERRORCODE=-4476, SQLSTATE=02501
How can I do this?
I use DB2 if that is of importance
Thanks for your help in advance.
TheVagabond
I don't know if you've tried the code, but if you did, what kind of exception are you getting?
You should try st.executeQuery instead of st.executeUpdate and then just compare if the returning number of count() function is bigger than 0
EDIT:
Seeing now your exception in your edited question:
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.
if (rc1.next()){
booleanVariable = true;
}
This will set the boolean variable in true if the variable resultSet (rc1) is returning something, it means that in the database there is data according to the query you made. If it returns false then it is empty.
I hope it can help you. Greets.
You should callResultSet.next() method first to move the cursor to the first row.
boolean check;
String sqlmd="select count(*) as Counter from tablename where mdsum = '"+mdSum+"' and filename = '"+Filename+"'";
rc1=st.executeQuery(sqlmd);
rc1.next();
Counterval=rc1.getInt("Counter");
if(Counterval > 0){
// do something
}else{
// do something
}
System.out.println("VAL: "+Counterval);
According to docs of next method -
Moves the cursor forward 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.
For better understanding read this answer.
I'm fairly new to Java and I was wondering how I could get all of the columns of a returned via MySQL query. For instance,
SELECT * FROM `login`
And then I had this code to return the results:
while (rs.next()) {
for (byte i = 1; i < 10; i++) {
result = result+" "+rs.getString(i);
}
}
I want 10 in the for loop to be the maximum number of columns because of dynamic MySQL queries. Is there a simple way to do this? Thanks.
Although, as duffymo suggested, it's better to spell out the columns you want to receive in the query, you can use ResultSet metadata to fetch the number of columns returned:
ResultSetMetaData rsmd = rs.getMetaData();
int numberOfColumns =rsmd.getColumnCount();
while (rs.next()) {
for (byte i = 1; i <= numberOfColumns; i++) {
result = result+" "+rs.getString(i);
}
}
Yes, you'd limit the fields that are returned. That's a SQL issue, not a Java issue. Change your query to something like this:
select this, that, theothercolumn from mytable;
Then you can use this to limit it dynamically:
rs.getMetaData().getColumnCount()
I'd recommend not using SELECT *. If you know the columns you want, spell them out. It'll make your code more robust in the face of column changes and reduce the number of bytes on the wire.
i need to create a client-server connection (in JAVA), where the server is connected to a database and the client can send queries and get answers.
I use the OCSF (by Dr. Timothy C. Lethbridge) , and JDBC driver for JAVA.
at the server's side, i have the following code
ResultSetMetaData rsmd=rs.getMetaData();
int numOfCols=rsmd.getColumnCount();
String[] tuple=new String[numOfCols];
Vector result=new Vector();
while (rs.next()){
for (int i=1;i<=numOfCols;i++)
tuple[i-1]=rs.getString(i);
result.addElement(tuple);
isResultEmpty=0;
}
if (isResultEmpty==0)
this.sendToAllClients(result);
else
this.sendToAllClients("No appropriate results!");
so far, it seems to work fine, i made some test-prints if the for loop and it works fine.
for the client side, i have the following code:
public void handleMessageFromServer(Object msg)
{
//clientUI.display(msg.toString());
if (msg instanceof Vector){
Vector result=(Vector)msg;
System.out.println("The result of the query is:\n\n");
//System.out.println((String)result.firstElement());
System.out.println("result size is "+result.size());
for (int i=1;i<=result.size();i++){
System.out.println("here");
System.out.println((String)result.get(i));
System.out.println("here2");
}
}
else
clientUI.display(msg.toString());
}
the problem starts when i try to print the results:
the first "here" is printed, and nothing else happens,
it never gets to the "here2", and seems to just terminate the printing and waits for new input.
is there any problem with the casting I make?
i just can't figure out where is the exact problem....
thank you very much in advance for helping
You don't have a vector of String objects. You have a vector of string arrays (String[])
Edit in response to comments:
System.out.println("result size is "+result.size());
for (int i = 0;i < result.size();i++){
System.out.println("here");
String[] array = (String[])result.get(i));
for (int j = 0; j < array.length; j++)
System.out.println(array[j]);
System.out.println("here2");
}
This is of course assuming the server side works. I didn't look at it closely.
Edit for server side:
This is all kinds of broke:
while (rs.next()){
for (int i=1;i<=numOfCols;i++)
tuple[i-1]=rs.getString(i);
result.addElement(tuple);
isResultEmpty=0;
}
On each loop iteration, you're simply changing what your string array contains, and adding the same reference over and over. You need:
String[] tuple;
while (rs.next()){
tuple = new String[numOfCols];
for (int i=1;i<=numOfCols;i++)
tuple[i-1]=rs.getString(i);
result.addElement(tuple);
isResultEmpty=0;
}
First thing that I noticed is your iteration starts at one and goes through the size (inclusive). You must start at zero and go through the size (exclusive). i=0,i
In the client code, I don't understand the while loop. When you call rs.next() (I am assuming here rs is a ResultSet), you move your pointer one more, unless there are no more entries. Then it seems that you iterate through all the items again. I may be incorrect, as I am unfamiliar with the usage of ResultSet, though from browsing the JavaDoc, it seems problematic.
Try printing the raw msg in your client code, see what spits out. Also go ahead an do the same after the cast, see if the output makes sense.
You should not be passing a ResultSet around at all. It's an interface that does not extend Serializable. It's an abstraction for a database cursor. When you pass it from one machine to another, without any information about the connection, what do you expect to happen? I don't see how it can work.
A ResultSet should never be passed out of the method in which it was created. The right thing to is the load it into an object or data structure, close it in a finally block, and return the object or data structure.
Your code is riddled with problems, but I think this is the chief one.