簡體   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