PSQLException: ResultSet not positioned properly, perhaps you need to call next - java

public UserBean authenticate(String username,String password){
PostGresDAO pg=new PostGresDAO(); //creates new connection
Connection conn=pg.getConnecion(); //return connection object
PreparedStatement ps;
ResultSet rs;
String query="select password,name from scg_users where username=?";
UserBean ub=null;
boolean authenticated=false;
try{
ps=conn.prepareStatement(query);
ps.setString(1, username);
rs=ps.executeQuery();
if(rs!=null){
authenticated=password.equals(rs.getString(1)); //exception raised here
if(authenticated){
ub=new UserBean();
ub.setUser(rs.getString(2));
ub.setUsername(username);
}
}
}
catch(SQLException e){
e.printStackTrace();
}
return ub;
}
I am using this code for authenticating a user. The username and password are extracted from the request parameter and passed onto this method for authentication. But it throws a:
org.postgresql.util.PSQLException: ResultSet not positioned properly, perhaps you need to call next.
Please advice.

The error is telling you exactly what's wrong - you're not calling next() on your ResultSet to get to the first row of the results.
This line:
if(rs!=null)
is pointless as far as I know; I don't believe executeQuery will ever return null. If there's a problem in your query, an exception will be thrown. If there are no results, it will return an empty result set. To see if there's a row, you should call next() and check the return value:
if (rs.next())
Additionally:
Catching an exception and just printing the stack trace without rethrowing is almost always the wrong approach
Your code suggests that you're storing passwords in plain text. Please don't. Really, really don't.

Because I got the message even when I called next() on resultSet I'll tell my solution.
The solution is NOT to call resultSet.get* on your resultSet if it's empty. So do a check if(resultSet.next()){ ...

Instead of
if(rs!=null)
You need to check for
if(rs.next())
This will return the first row, if there are any matching rows.

Maybe you have resultSet.next() in debugger Inline Watches :)
It was the case for me;
So my check if (resultSet.next()) returns true but when I go inside the if block, the next() is called again and then there is no data so I got the same error message

Related

How to check if entered value is equal to a value in a sql database

I have a database with 7 rows, and 4 columns in each. I am prompting a user to enter a code, and I need to cross reference the database to see if the entered code equals one of the codes in the database (first column in each row).
At first, I was checking if the result set came up as null, but that was not working. I was tryingif(rs.wasNull()) but it never seemed to execute.
Does anybody have any advice on what to look at to solve my issue? Here's a code snippet if helps at all.
if(!rs.wasNull()) {
while(rs.next()) {
Products temp = new Products(rs.getString(1), rs.getString(2), rs.getDouble(3), rs.getBoolean(4));
productsList.add(temp);
// For testing purposes
//out.println(temp.toString());
request.setAttribute("productsList", productsList);
request.getRequestDispatcher("Scan.jsp").forward(request, response);
}
}
else if(rs.wasNull()) {
Products wrongCode = null;
productsList.add(wrongCode);
request.setAttribute("productsList", productsList);
request.getRequestDispatcher("Scan.jsp").forward(request, response);
}
edit: I now know that ResultSet never returns null. It will return an empty ResultSet.
edit2: I've wrote this method to solve the problem:
public boolean codeExists(int code) {
final String SELECT_QUERY = "SELECT * FROM productcatalogue WHERE code = ?";
try {
PreparedStatement statement = conn.prepareStatement(SELECT_QUERY); // Create query statement
statement.setInt(1, code);
ResultSet queryResult = statement.executeQuery();
if (!queryResult.next()) { // Check if code entered exists
return false; // Tells that the author doesn't exist
}
} catch (SQLException sqlException) {
sqlException.printStackTrace();
}
return true; //Otherwise the item exists
}
If the result is empty it will never go into while loop. This is a condition which is used to separate code logic. Calling additional code on the result set is useless.
You should check the jdbc api for ResultSet#wasNull():
wasNull
boolean wasNull()
throws SQLException
Reports whether the last column read had a value of SQL NULL. Note that you must first call one of the getter methods on a column to try to read its value and then call the method wasNull to see if the value read was SQL NULL.
Returns:
true if the last column value read was SQL NULL and false otherwise
Throws:
SQLException - if a database access error occurs or this method is called on a closed result set

how to handle java sql exception:exhausted result set [duplicate]

This question already has answers here:
SQLException: Exhausted Resultset
(3 answers)
Closed 7 years ago.
i have problem with the below code. help me!!
Class.forName("oracle.jdbc.driver.OracleDriver");
Connection conn=DriverManager.getConnection("jdbc:oracle:thin:#127.0.0.1:1521:xe","system","**********");
Statement st=conn.createStatement();
String sql="select password from db where username='user'";
ResultSet rs=st.executeQuery(sql);
rs.next();
String password=rs.getString("password");
if(password.equals(pass))
{
RequestDispatcher rd=req.getRequestDispatcher("/home.jsp");
rd.forward(req,res);
}
else
{
out.println("invalid username and password");
}
when i execute this code i am getting an java sql exception : exhausted result set. thanks in advance...
Instead of using rs.next();, use it with while e.g while(rs.next()). Once you got the resultset, the pointer will point to the first record. Each time you do a rs.next(), the pointer will advances to the next record. If you use with while, once you reach to the end of your resultset, rs.next() will return false once all records are iterated. In your case, since you are not checking whether resultset has exhausted and trying to advanced the pointer, you are getting the exception.
That is correct, because if you enter wrong username or password, NO record will be returned. So, when you use the rs.next(); in this case, it is trying to access the first row of the empty result set
String password=rs.getString("password");//error, if rs is empty
in the where clause you are not using user variable
where clause should be where username='"+user+"'";
and
instead of
rs.next();
use
if(rs.next())
{
String password=rs.getString("password");
........
}

Why is it not getting into the if condition?

I have this code.
public String Login(String email, String password) {
String mode = "";
try {
con = DriverManager.getConnection(url, userdb, passdb);
Statement select = con.createStatement();
ResultSet result = select.executeQuery("SELECT * FROM doit WHERE DoitEmail='" + email + "' AND DoitPassword='" + password + "'");
if (result.first()) {
mode = "doit";
}
} catch (SQLException ex) {
}
return mode;
}
What seems to be the problem why is it not returning the value for mode inside the if statement.
In other words, why is it not executing the if statement block, when I debug, it directly goes to return mode without setting new value for mode?
UPDATE: Im using the new code... (it has the single quote at the end..)
UPDATE2: Problem solved,,,
You're missing a closing quote, change:
DoitPassword='"+password+""
to:
DoitPassword='"+password+"'"
Further, like was already commented above, it's bad practice to catch exceptions without (at least) printing the error to log.
And last, I'd like to introduce you to one of my good friends: Bobby Tables
It is not going into the if condition because you the ResultSet's cursor is not at the first row.
The result.first() method returns true only when the ResultSet's cursor is pointing at the first row.
Either try calling result.isFirst() or call result.next() before calling result.first().
Hope this helps!
Unrelated
You may try MySQL JDBC Utilities API for easy Java-MySQL tasks.

Prepared statement not returning results for string numbers

I am trying to retrieve records from oracle database for the SQL query - SELECT data FROM test where id = ?;
Here is my code to retrieve the data -
public static String retrieveData(String id) throws IOException {
String result = "";
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
String sql = "SELECT data FROM test where id = ?";
connection = getDBConnection(); //this method gets the db connection
ps = connection.prepareStatement(sql);
ps.setString(1, id);
rs = ps.executeQuery();
while(rs.next()) {
result = result + rs.getString("data");
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
closeDBConnection(); //closes db connection
}
return result;
}
When I invoke the retrieveData in the main method, it returns null. When I debug, the resultSet is empty. I am guessing the reason is I am passing my id as String, but perhaps Oracle doesn't understand something like - SELECT data FROM test where id = "1234567890";
Can someone please guide me how do I fix this? I have tried way too many things, but I can't seem to fetch the data from the db for this id. I also tried converting the id to long using Long.valueOf(String s).longValue(); and setting this as the placeholder in ps.setLong, but it didn't help. Please advise.
Type issue of id column
This is probably due to spacing difference or another subtle difference that gives the impression that they are the same.
The strings ' 123 ' or '00123' (for example) are not equivalent to '123' in VARCHAR2 type, while they are equivalent in NUMERIC type, as Oracle converts all those strings to the numeral 123.
You are better off using a NUMERIC column as your id to avoid such problems. It also makes sense to limit your valid id values to whole numbers, rather than any arbitrary string.
With Oracle you can continue to use setString as it will automatically cast the string to an integer. But I recommend you to use setInt or setLong instead (after the conversion of the id column), as other database solutions like Postgres will not accept a string to match a NUMERIC column.
Exception handling issue
When you catch a Throwable or an Exception (or their subtypes), be sure to think about whether it can be ignored, or it must be thrown for further handling (for example, to stop the program, alert the user or correct the problem).
In your code, the catch block catches the SQLException and prints the stack trace. But it doesn't do anything else.
} catch (SQLException e) {
e.printStackTrace();
} ...
This means that you are ignoring the exception and continuing the program as though nothing happened. The execution will continue on to return result; after completing the finally block.
The caller of your method will never know that an SQLException occurred, and it will wrongly assume that there were no errors and the returned data is correct.
Unless that is what you really want, what you ought to do is as follows:
} catch (SQLException e) {
e.printStackTrace(); //it doesn't matter what you do here. the next line is what's important.
throw e; //throw the exception after printing stack trace, logging, etc.
} ...
In this case your method will throw the SQLException to the caller after completing the finally block. The execution will not continue to return result;.
This way the caller of your method will receive the exception and know that an error has occurred. The caller can then act accordingly; for example, by stopping the program, alerting the user or retrying the method with a different input.
may be the reason is DEBUG. if you have a breakpoint on the line "while(rs.next())" and you watch/inspect it then then rs increments one. Then the code executes rs.next for the second time where there is no record.
maybe...
You shouldn't use datatype 'String' for id field, it can cause serious trouble. Try to covert it to numeric datatype is possible but why don't you use numeric at first. You should change to int or bigint. In additional try to catch exception like this:
try{
}catch(SQLException ex){
System.out.println("Error at:" +ex.getClass().getName() + ex.getMessage());
}
Try it again, if you can't debug it and find out why! Good luck!
Please try this. Remove all the spaces when defining field name with a ? and check
SELECT data FROM test where id=?

Can a ResultSet be 'null' in Java?

I have a very basic bit of code which executes a select query and returns a boolean depending if the result set is empty or not.
public boolean checkIfUserHasPreferences(String username){
ResultSet rs = null;
boolean checkBoolean = false;
try {
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
con = DriverManager.getConnection(Messages.getString("OracleUserManagement.0"), Messages.getString("OracleUserManagement.1"), Messages.getString("OracleUserManagement.2")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
PreparedStatement statement = con.prepareStatement("SELECT USERNAME FROM USER_PREFERENCES WHERE USERNAME = ?");
statement.setString(1, username);
rs = statement.executeQuery();
if (rs == null){
System.out.println("I checked it was true!");
checkBoolean = true;
} else {
System.out.println("I checked it was false!");
checkBoolean = false;
}
con.commit();
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
return checkBoolean;
}
What confuses is me that even though the table/database is empty, it always prints out "I checked it was false!".
Is this because even if a result set returns 0 rows, it does not = null? Should I be using while (rs.next()) to check instead?
You could have looked onto the API of Statement#executeQuery() method. It says:
Returns:
a ResultSet object that contains the data produced by the given query; never null
Emphasis mine.
Should I be using while (rs.next()) to check instead?
Yes.
No, ResultSet returned by executeQuery(java.lang.String) method can never be null.
Moreover, the standard way to check whether a ResultSet is empty or not is to try setting its cursor to first row by using its first() and if it returns false it indicates that ResultSet is empty.
So, in your case you don't even need to check rather just return rs.first();
For example:
if (!rs.first()) {
// handle empty set: throw error or return
}
// continue processing the ResultSet further
do {
// ...
} while (rs.next());
The result set will not be null until and unless:
1.It is initialized to null and done nothing else,
2.If the statement on which execute query is written is not correct(sql exception will occur and initialization will not happen).
This is irrelevant for this question, but will serve as a tip for people like me.
This happen when database operation is done in a separate class where statement.executeQuery() is given in try-catch which has no e.printStackTrace() or any other logging mechanics.
I have confronted with this error and that is the reason why I am writing. This can be a great problem when we do a batch process where one out of 50000 execution causes an exception(in my case:
com.ibm.db2.jcc.a.SqlException: DB2 SQL error: SQLCODE: -805,
SQLSTATE: 51002
this error was caused around 20000 iteration ) which causes unwanted result.

Categories