简体   繁体   中英

Java SQL Exception - r.getString doesn't get column from resultSet

I keep getting SQLException on String passwordr = r.getString(3); . From my understanding is that r.getString gets column 3 from the result set, which contains the password in table. Later on I will compare passwordr to whatever is in txtPassword. Why does it keep going to SQL Exception?

If I hover over "passwordr" it says "Not a known variable in the current context" within NetBeans - I'm not sure if this matters.

   try{
        // load the sql driver
        Class.forName(ConnectionDetails.getDriver());
         
        // attempt to connect
        con = DriverManager.getConnection(url, username, password);
        System.out.println("Connected to the database: "+  ConnectionDetails.getDb());
            
        // prepare an sql statement
        stmt = con.createStatement();
            
        String sql = "SELECT * FROM tblusers WHERE fldusername='" + txtUsername.getText() + "';"; 
        
        // run the query
        System.out.println("Before query");
        System.out.println(sql);
        r = stmt.executeQuery(sql);
        System.out.println("After query");
 
        String passwordr = r.getString(1);  //FAILS AT THIS LINE
        System.out.println(passwordr); 
        
        if ( r.next() )// if this returns false there are no records
        {
                // username found     
                lblResult.setText("USERNAME Found");
                
                if (passwordr.equals(new String((txtPassword.getPassword()))))
                {
                    lblResult.setText("PASSWORD Correct");
                }
                else
                {
                    lblResult.setText("PASSWORD Incorrect");
                }
                
        }
        else      
        {
               lblResult.setText("USERNAME NOT FOUND");
        }
        
  
       
        }
        catch(ClassNotFoundException cnfe)
        {            System.err.println("Error finding connection details class");
        }
        catch(SQLException sqlE)
        {
            System.err.println("SQL Error");
        }
        finally
        {
            // close the statement object
            try
            {
                if( stmt != null )
                    stmt.close();
                
                System.out.println("Statement object closed");
            }
            catch(SQLException se)
            {
                System.err.println("Error:  Statement not closed");
            }
            
            // close connection to the database
            try
            {
                if( con != null )
                    con.close();
                
                System.out.println("Connection to db closed");
            }
            catch(SQLException se)
            {
                System.err.println("Error:  Connection to db not closed");
            }
        }    
        
            
    }

This block of code has multiple issues, some minor and some significant. The version I am providing here still has some issues, but addresses many of the problems of the original code.

Orthogonal to the problem of getting this code to work is the larger question of whether it is appropriate to store passwords in plaintext in a database. I won't address that here, as this is still an appropriate bit of code for learning Java and JDBC.

See the commented note pointers in the code.

try{
  // load the sql driver
  Class.forName(ConnectionDetails.getDriver());

  // attempt to connect
  con = DriverManager.getConnection(url, username, password);
  System.out.println("Connected to the database: "+  ConnectionDetails.getDb());

  // prepare an sql statement
  String sql = "SELECT * FROM tblusers WHERE fldusername=?"; // <----- Note 1

  // Now we need to use a prepared statement, so we can use a bind variable
  stmt = con.prepareStatement(sql);

  // Bind the user data
  stmt.setString(1, txtUsername.getText()); // <----- Note 2

  // run the query
  System.out.println("Before query");
  System.out.println(sql);
  r = stmt.executeQuery();
  System.out.println("After query");

  if ( r.next() )// if this returns false there are no records   // <----- Note 3
  {
    String passwordr = r.getString("PASSWORD_FIELD_NAME"); // <----- Note 4
    System.out.println(passwordr);

    // username found
    lblResult.setText("USERNAME Found");

    if (passwordr.equals(new String((txtPassword.getPassword()))))
    {
      lblResult.setText("PASSWORD Correct");
    }
    else
    {
      lblResult.setText("PASSWORD Incorrect");
    }
  }
  else
  {
    lblResult.setText("USERNAME NOT FOUND");
  }
}
catch(ClassNotFoundException cnfe)
{
  System.err.println("Error finding connection details class");
}
catch(SQLException sqlE)
{
  System.err.println("SQL Error");
}
finally
{
  // close the Result Set object        // <----- Note 5
  try
  {
    if( r != null )
    r.close();

    System.out.println("Result set object closed");
  }
  catch(SQLException se)
  {
    System.err.println("Error:  Result set not closed");
  }
  // close the statement object
  try
  {
    if( stmt != null )
    stmt.close();

    System.out.println("Statement object closed");
  }
  catch(SQLException se)
  {
    System.err.println("Error:  Statement not closed");
  }

  // close connection to the database
  try
  {
    if( con != null )
    con.close();

    System.out.println("Connection to db closed");
  }
  catch(SQLException se)
  {
    System.err.println("Error:  Connection to db not closed");
  }
}
  1. The original SQL was being created with user-provided text in a quoted string. This kind of construct is just begging for a SQL Injection attack. It is almost always best to use bind variables instead. In the very rare case where that cannot be done, the user-provided data must be sanitized. Do some research on SQL Injection Attack to see how easy it is for someone to get your code to execute unwanted SQL. Besides the benefit for security, bind variables improve the database's ability to share the parsed SQL. In order to use bind variables, you will need to use PreparedStatement instead of Statement . Finally, the trailing semicolon in the SQL is not needed (at least in Oracle, not sure about others) and might cause syntax issues.
  2. This is where the binding happens. The statement has been created, but now we have to bind the user-provided value.
  3. You won't have any results until you first call r.next() .
  4. It is far safer to get the data from the result set by column name vs. position. This is particularly important when working with large numbers of columns, as database tables might have different column order in Dev/Test/Stage/Prod based on how they were modified over time.
  5. To be pedantic, the result set should also be closed. In order to simplify all of these verbose try/catch sections, consider using "Try with resources".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM