繁体   English   中英

Java SQL 异常 - r.getString 没有从 resultSet 中获取列

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

我不断收到 SQLException on String passwordr = r.getString(3); . 根据我的理解,r.getString 从结果集中获取第 3 列,其中包含表中的密码。 稍后我会将 passwordr 与 txtPassword 中的任何内容进行比较。 为什么它会继续出现 SQL 异常?

如果我将鼠标悬停在“passwordr”上,它会在 NetBeans 中显示“在当前上下文中不是已知变量”——我不确定这是否重要。

   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");
            }
        }    
        
            
    }

这段代码有多个问题,有些是次要的,有些是重要的。 我在这里提供的版本仍然存在一些问题,但解决了原始代码的许多问题。

与让这段代码正常工作的问题正交的是一个更大的问题,即在数据库中以明文形式存储密码是否合适。 我不会在这里解决这个问题,因为这仍然是学习 Java 和 JDBC 的合适代码。

请参阅代码中的注释注释指针。

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. 最初的 SQL 是用用户提供的带引号的字符串创建的。 这种构造只是在乞求 SQL 注入攻击。 最好使用绑定变量来代替。 在极少数情况下无法做到这一点,必须清理用户提供的数据。 对 SQL 注入攻击进行一些研究,看看有人让您的代码执行不需要的 SQL 是多么容易。 除了安全方面的好处之外,绑定变量还提高了数据库共享已解析 SQL 的能力。 为了使用绑定变量,您需要使用PreparedStatement而不是Statement 最后,不需要 SQL 中的尾随分号(至少在 Oracle 中,其他不确定)并且可能会导致语法问题。
  2. 这是绑定发生的地方。 语句已创建,但现在我们必须绑定用户提供的值。
  3. 在您第一次调用r.next()之前,您不会有任何结果。
  4. 按列名与位置从结果集中获取数据要安全得多。 这在处理大量列时尤为重要,因为数据库表在 Dev/Test/Stage/Prod 中可能具有不同的列顺序,这取决于它们随时间的修改方式。
  5. 为了学究,结果集也应该关闭。 为了简化所有这些冗长的 try/catch 部分,请考虑使用“尝试资源”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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