有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

jdbc Java SQL异常r.getString未从resultSet获取列

我一直在stringpasswordr=r.getString(3)上获取SQLException。据我所知,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");
            }
        }    
        
            
    }

共 (1) 个答案

  1. # 1 楼答案

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

    与使该代码正常工作的问题正交的是一个更大的问题,即在数据库中以明文形式存储密码是否合适。我不会在这里讨论这个问题,因为这仍然是学习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. 为了迂腐,结果集也应该关闭。为了简化所有这些冗长的尝试/catch部分,请考虑使用“尝试与资源”。<李>