Getting "java.sql.SQLException: Values not bound to statement" exception - java

I was trying to make a program which consists of connecting an user by a login system with SQL, then if the credentials are good the user is redirected to an another frame.
But I had a problem, I want to have some information in the SQL base, so I have tried to use while loop and it was working, but after I encountered an error :
java.sql.SQLException: Values not bound to statement
See the following code :
String pseudo2 = null;
String rank2 = null;
try {
String searchname2 = "select * from AdminsInfos where pseudo=?";
PreparedStatement name2 = connection.prepareStatement(searchname2);
ResultSet rspseudo2 = name2.executeQuery();;
while (rspseudo2.next())
{
pseudo2 = rspseudo2.getString("Pseudo");
rank2 = rspseudo2.getString("Rank");
}
} catch (Exception e2) {
e2.printStackTrace();
}
JOptionPane.showMessageDialog(null, "Username and password are correct, connection Admin !");
frame.setVisible(false);
new LoginMain().setVisible(true);
LoginMain.usernameField.setText(pseudo2);
LoginMain.ranklabel.setText("Rank : " + rank2);
and you can check the SQL base too by the following picture :
sql base
Can someone help me?

Since you have a bound variable you need to set the value before executing the statement.
for example , if psuedo is of type String then you will be doing something like below.
String searchname2 = "select * from AdminsInfos where pseudo=?";
PreparedStatement name2 = connection.prepareStatement(searchname2);
name2.setString(1,"value");
ResultSet rspseudo2 = name2.executeQuery();
where first parameter in the setString means you want to set the first value for the bound variable.

Related

JDBC and MySQL Statement and ResultSet error

I am trying to run the following code:
Scanner input = new Scanner(System.in);
ResultSet rs = null;
System.out.print("Username: ");
String username = input.next();
System.out.print("\nPassword: ");
String pword = input.next();
String stmt = "SELECT * FROM accounts WHERE username = '"+username+"' AND password = '"+pword+"' ";
Statement s = con.createStatement(); // con = Connection object
rs = s.executeQuery(stmt);
if(rs.absolute(1)) {
System.out.println("LOGIN SUCCESSFUL");
}
else {
System.out.println("INVALID LOGIN");
}
However, I end up with the following error:
java.sql.SQLException: Operation not allowed for a result set of type ResultSet.TYPE_FORWARD_ONLY.
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.result.ResultSetImpl.absolute(ResultSetImpl.java:391)
at practice.JDBCtester.login(JDBCtester.java:36)
at practice.JDBCtester.main(JDBCtester.java:17)
Could someone explain the problem with my code?
Instead of using absolute() you can just verify at least one row was returned. For example you can do:
rs = s.executeQuery(stmt);
if (rs.next()) {
System.out.println("LOGIN SUCCESSFUL");
}
else {
System.out.println("INVALID LOGIN");
}
absolute() is an advanced method useful for reading, re-reading, and updating special types of result sets. Your result set is a simple one.
As documented in the ResultSet.absolute(int):
Throws:
  SQLException - if a database access error occurs; this method is called on a closed result set or the result set type is TYPE_FORWARD_ONLY
In most situations, the default result set type is TYPE_FORWARD_ONLY, so the absolute method is not supported.
Instead use ResultSet.next() to check if there is at least one row.
As I also commented, your current code is highly insecure. Don't concatenate values into a query string (especially not values obtained from a user), as this makes your code vulnerable to SQL injection. Instead use a prepared statement with parameter placeholders. Also don't store plaintext passwords, but use an appropriate password hashing algorithm.

Got stuck in password change code

I make this code for change password with verification. The problem is, when I clicked jbutton to change password, it works and successfully changed the password on database and show the jOptionpane Information message as well.
But after this steps, error message functioned jOptionpane is continuously showing. I try to find where the code was wrong. but couldn't yet.
private void jBtn_UpdateActionPerformed(java.awt.event.ActionEvent evt) {
String user_id = txt_UserID.getText();
String cur_pass = txt_CurrentPassword.getText();
String new_pass = txt_NewPassword.getText();
try {
Connection c = DBConnection.dbconmethod();
Statement s = c.createStatement();
ResultSet rs = s.executeQuery("SELECT * from tch_data");
while(rs.next()) {
String userid = rs.getString("user_id");
String pass = rs.getString("password");
if(user_id.equals(userid) && cur_pass.equals(pass)) {
Statement s1 = c.createStatement();
s1.executeUpdate("UPDATE tch_data SET password='"+new_pass+"' WHERE user_id='"+user_id+"'");
JOptionPane.showMessageDialog(new view.AdminPrivacy(), "Password Succesfully Changed!", null, JOptionPane.INFORMATION_MESSAGE);
}else {
JOptionPane.showMessageDialog(new view.AdminPrivacy(), "Error : Invalid Data.", "Error Message", JOptionPane.ERROR_MESSAGE);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
You're retrieving all the rows in the database, for all the users, with your SQL query
Statement s = c.createStatement();
ResultSet rs = s.executeQuery("SELECT * from tch_data");
Of course your username and password do not match all the rows (since you'll be seeing all the users in your database in your loop) so you always get an error message for each row except for the one that has your user in it.
You should change the query to only return the row for the user that you're changing the password for. However that requires you to use a PreparedStatement. (If you simply used the user_id in the query for a regular Statement without escaping, you'd make yourself subject to SQL injection attacks. Note that also applies to the place where you update the password - you should also use a PreparedStatement for that, otherwise you'll be in for a nasty surprise when somebody changes his password to '; DROP TABLE tch_data; SELECT * FROM tch_data 'foobar or something along those lines)
So you should replace the above two lines with these 3 lines:
PreparedStatement st = c.prepareStatement("SELECT * from tch_data WHERE user_id = ?");
st.setString(1, user_id);
ResultSet rs = st.executeQuery();
Note that you've also forgotten to close your ResultSet, Statement and Connection. You should close all of them (but most importantly the Connection), otherwise you're leaking them and your application will quickly run out of resources.
Once the Password change has been successfully made, you should break out of the while loop using the break statement. The else statement within the while loop should also be removed and placed outside of the loop. A boolean flag should be set so as to determine whether or not a successful password change has taken place and that condition checked outside the loop, for example:
try {
Connection c = DBConnection.dbconmethod();
Statement s = c.createStatement();
ResultSet rs = s.executeQuery("SELECT * from tch_data");
boolean success = false; // **** Added Code ****
while(rs.next() && success == false) {
String userid = rs.getString("user_id");
String pass = rs.getString("password");
if(user_id.equals(userid) && cur_pass.equals(pass)) {
Statement s1 = c.createStatement();
s1.executeUpdate("UPDATE tch_data SET password='"+new_pass+"' WHERE user_id='"+user_id+"'");
success = true; // **** Added Code ****
JOptionPane.showMessageDialog(new view.AdminPrivacy(), "Password Succesfully Changed!", null, JOptionPane.INFORMATION_MESSAGE);
break; // **** Added Code ****
}
}
// **** Added Code ****
if (!success) {
JOptionPane.showMessageDialog(new view.AdminPrivacy(), "Error : Invalid Data.", "Error Message", JOptionPane.ERROR_MESSAGE);
}
} catch (Exception e) { e.printStackTrace(); }
I fully agree with Erwin Bolwidt's answer, and it is IMHO the correct answer.
Since you also asked why you end up with messagedialogues --> because you're loading all users!!!
and your if-else block is wrong. if you're only changing/checking the password for one single user!
// make sure that it's the correct user
if(user_id.equals(userid)) {
// check if password was changed successfully
if(cur_pass.equals(pass)) {
// successful password change
} else {
// something went wrong with the password change
}
} else {
// this else is just to help you see your mistake
// in your code you raised the error here!
}

Unable to get value from ResultSet

I am working on a web application using Java and MySQL.
I created a method that is supposed to return an ArrayList of the respective column name based on the various tables in the database.
However, when I debugged the method, I realised the while(rs.next()) causes an error. I used this site for reference, hence I am not sure what went wrong.
This is the code. Thanks.
// Returns the the all the columns in the table
public ArrayList getColumnName(String tableName) throws SQLException {
ResultSet rs = null;
List<String> columnName = new ArrayList<String>();
Statement st = null;
Connection con = null;
try {
// Get a connection from the connection factory
con = DriverManager.getConnection("jdbc:mysql://localhost:3306/information_schema", "root", "xxxx");
// Create a Statement object so we can submit SQL statements to the driver
st = con.createStatement();
StringBuilder sql = new StringBuilder("SELECT column_name FROM information_schema.columns " +
"WHERE table_schema = 'testDB' AND table_name = '");
sql.append(tableName).append("'");
rs = st.executeQuery(sql.toString());
while (rs.next()) { // getting error..
columnName.add(rs.getString("column_name"));
}
} catch (SQLException ex) {
Logger.getLogger(ModificationPage.class.getName()).log(Level.SEVERE, null, ex);
} finally {
if (con != null || st != null) {
st.close();
con.close();
}
}
return (ArrayList) columnName;
}
According to the Javadoc of 1.6 (not sure which version of Java you're using):
Throws:
SQLException - if a database access error occurs or this method is called on a closed result set
It's very, very unlikely that if you actually got to the line where rs.next() was called, that a database error occurred just then. So, the most likely result is that the result set was closed.
Please alter your code to the following and see if you still get the error on the same line:
while (!rs.isClosed() && rs.next()) { // getting error..
columnName.add(rs.getString("column_name"));
}
Also, Holy SQL Injection Attack, Batman!
Taking the raw string as you're doing and enclosing it within single quotes leads this code to have an SQL injection vulnerability. Basically all a malicious user has to do is end your query with a single quote (') and run a query of their own afterwards.
So, the exception never happens ?
A query error should be thrown at rs = st.executeQuery(sql.toString()) if that were the case, but if it make it to whileand didn't iterate, it's because of an empty resultset
Maybe you're passing wrong arguments to the query ?

search in postgreSQL

I have been able to link postgresql with java. I want the user to input a name in a text box in java and a search is performed and checks if the name exists in the database.
My code so far:
String hostname=this.hostNameText.getText();
try
{
s = connection.createStatement();
String q="SELECT * FROM hostdetails WHERE \"HOSTNAME\" = "+hostname;
rs = s.executeQuery(q);
}catch(Exception e)
{
System.out.println("Problem in searching the database 1");
}
I am getting problem to link to the table hostdetails. Please note that hostdetails contain a field nammed HOSTNAME(in capital letters). When I run the above code, I get "Problem in searching the database 1"is displayed. Kindly please help me:)
Try using parameterized queries to protect against SQL injection. Use as follows:
String hostname=this.hostNameText.getText();
try
{
String q="SELECT * FROM hostdetails WHERE \"HOSTNAME\" = ?"; //notice change here
//and use params like this
PreparedStatement pStmnt = connection.prepareStatement(q);
pStmnt.setString(1, hostname);
rs = pStmnt.executeQuery(q);
}catch(Exception e)
{
//error handling here
}

ResultSet.getNext() not working with PreparedStatement

I am trying to figure out why ResultSet.next() is never true in Java code that I am writing after I execute a SQL query that returns results from an Oracle 11g table into that ResultSet... it seems as though the code does not pick up a returned ResultSet's contents correctly when using a PreparedStatement in a java.sql.Connection. Any help appreciated, here are the details:
Table:
CREATE TABLE "SHANDB"."ABSCLOBS"
( "ID" NUMBER,
"XMLVAL" "XMLTYPE",
"IDSTRING" VARCHAR2(20 BYTE)
)
Data:
INSERT INTO absclobs VALUES ( 1,
xmltype('<?xml version="1.0"?>
<EMP>
<EMPNO>221</EMPNO>
<ENAME>John</ENAME>
</EMP>', '1'));
INSERT INTO absclobs VALUES (2,
xmltype('<?xml version="1.0"?>
<PO>
<PONO>331</PONO>
<PONAME>PO_1</PONAME>
</PO>', '2'));
Java code I am running to get values from the above to test the code:
public static void main(String[] args) throws Exception {
try {
String url = "jdbc:oracle:thin:#//localhost:1521/xe";
String driver = "sun.jdbc.odbc.JdbcOdbcDriver";
String user = "shandb";
String password = "test";
Class.forName(driver);
connection = DriverManager.getConnection(url,user, password);
String selectID1 = "SELECT a.xmlval.getClobval() AS poXML FROM absclobs a where idstring=? and id=? ";
PreparedStatement preparedStatement = connection.prepareStatement(selectID1);
preparedStatement.setString(1, "1");
preparedStatement.setInt(2, 1);
rowsUpdated = preparedStatement.executeQuery();
while(rowsUpdated.next()){
String clobxml = rowsUpdated.getString(1);
System.out.println(clobxml);
}
} catch (ClassNotFoundException cnfe) {
System.err.println(cnfe);
} catch (SQLException sqle) {
System.err.println(sqle);
}
finally{
System.out.println("Rows affected: " + rowsUpdated);
connection.close();
}
}
This part of the above code is never run, which I don't understand:
while(rowsUpdated.next()){
String clobxml = rowsUpdated.getString(1);
System.out.println(clobxml);
}
... however the final print statement shows that the ResultSet is not empty:
Rows affected: oracle.jdbc.driver.OracleResultSetImpl#15f157b
Does anyone know why I can't display the actual retrieved XML clob contents, and/or why the while block above is never true?
Thanks :)
Your diagnostics are incorrect - this:
Rows affected: oracle.jdbc.driver.OracleResultSetImpl#15f157b
doesn't show that the result set is non-empty. It just shows that the value of rowsUpdated is a reference to an instance of oracle.jdbc.driver.OracleResultSetImpl, which doesn't override toString(). That can very easily be empty.
I suspect the problem is just that your WHERE clause doesn't match any records. For the sake of diagnostics, I suggest you change it to just:
String selectID1 = "SELECT a.xmlval.getClobval() AS poXML FROM absclobs a";
(and get rid of the parameter-setting calls, of course). That way you should be able to see all your table's values. You can then work on discovering why your WHERE clause wasn't working as expected.
(As an aside, it's not clear why you haven't declared connection or rowsUpdated in the code in the question. They should definitely be local variables...)

Categories