关于查询的Java MySQL NullPointerException

时间:2013-01-02 13:07:26

标签: java sql nullpointerexception

基本上我从数据库中获取ResultSet时遇到问题。错误发生在此代码块中的第34行(?)附近,但我已将其标记为

ResultSet rs = caq.executeQuery("SELECT * FROM ProjectScore"); //error goes here

我在运行时得到一个空指针异常,这是下面的catch语句的输出:

null, calculating average score failed

java.lang.NullPointerException

[Ljava.lang.StackTraceElement;@1de2b1

有趣的是,我最后在类中使用Connection完全相同,并且我没有收到任何错误。将语句复制到第一个类也不起作用,所以我认为它是另一个。我认为这就是我的全部,感谢任何帮助:)

import java.awt.*;
import java.awt.event.*;
import java.sql.*;

import javax.swing.*;

public class MainWindow extends JFrame implements ActionListener{
    //.......................
    private int [] averageScore;

    //References
    private LogInWindow liw;
    private NewUserWindow nuw;
    private ScoreWindow sw;
    private boolean isAnotherWindowOpen = false;
    private boolean isLoggedIn = false;
    private ConnectionAndQueries caq;

    public MainWindow(ConnectionAndQueries caq) throws SQLException{
        this.caq = caq;

        //.................................

        //Middle
        averageScore = new int [9];
        calculateAverageScore();
        setTable();

        //............................
    }

    private void calculateAverageScore() throws SQLException{
        try{
            ResultSet rs = caq.executeQuery("SELECT * FROM ProjectScore"); //error goes here
            int [] count = new int [9];
            int [] totalScore = new int [9];

            while(rs.next()){
                int itemID = rs.getInt("itemID");

                count[itemID]++;
                totalScore[itemID] += rs.getInt("Score");
            }

            for(int i = 0; i < 9; i++){
                averageScore[i] = totalScore[i] / count[i];
            }
        }
        catch (Exception e) {
            System.out.print(e.getMessage());
            System.out.println(", calculating average score failed");
            System.out.println(e.toString());
            System.out.println(e.getStackTrace().toString());
        }
    }
}




//next class

import java.sql.*;

public class ConnectionAndQueries {
    private static Connection connection;
    private static Statement statement;
    private MainWindow mw;

    public ConnectionAndQueries() throws ClassNotFoundException, SQLException{
        mw = new MainWindow(this);
        connect();
    }

    public static void connect() throws ClassNotFoundException, SQLException{
        try{
            Class.forName("com.mysql.jdbc.Driver");
            connection = DriverManager.getConnection("jdbc:mysql://zzzzzzzzzz", "yyyy",     "xxxx"); //dont think im allowed to give that info
            statement = connection.createStatement();
        } catch (Exception e) {
            System.out.println("Connecting to the database failed");
        }
    }

    public ResultSet executeQuery(String query) throws SQLException {
        return statement.executeQuery(query);
    }

    public int executeUpdate(String update) throws SQLException {
          return statement.executeUpdate(update);
    }

    public static void main(String [] args) throws ClassNotFoundException, SQLException{
        ConnectionAndQueries caq = new ConnectionAndQueries();
    }
}




//another class which uses the connection class, and works.

import java.awt.*;
import java.awt.event.*;
import java.sql.*;

import javax.swing.*;

public class LogInWindow extends JFrame implements ActionListener{
    //........................

    //References
    private MainWindow mw;
    private ConnectionAndQueries caq;

    public LogInWindow(MainWindow mw, ConnectionAndQueries caq){
        this.mw = mw;
        this.caq = caq;

        //......................
    }

    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == logIn){
            String usn = usernameField.getText();
            String pwd = passwordField.getText();

            try {
                ResultSet rs = caq.executeQuery("SELECT * FROM ProjectCustomer");

                while(rs.next()){
                    if(rs.getString("username").equals(usn)){
                        if(rs.getString("passwrd").equals(pwd)){
                            logInSuccess(usn);
                            mw.userLoggedIn(usn);
                            quit();
                        }
                    }
                }

                if(mw.isUserLoggedIn() == false)
                    logInFailed();

            } catch (Exception e2) {
                System.out.print(e2.getMessage());
                System.out.println(", error at log in");
                System.out.println(e2.toString());
            }
        }

        else if(e.getSource() == quit){
            quit();
        }
    }

    //............................
}

3 个答案:

答案 0 :(得分:3)

当调用此构造函数时,它会将自身的引用发送给MainWindow。

public ConnectionAndQueries() throws ClassNotFoundException, SQLException{
    mw = new MainWindow(this);
    connect();
}

但是,由于在引用的对象尚未构造时发送此引用(即构造函数尚未完成),此时引用只能为null。

修复此问题的一种方法是将代码从构造函数移动到主方法,在 new ConnectionAndQueries()下面。但是,我强烈建议重构程序结构,将数据库连接和操作分成一个或多个单独的类,以及将UI代码与数据库代码分离。

答案 1 :(得分:2)

问题是因为构造函数。

  

public ConnectionAndQueries()抛出ClassNotFoundException,SQLException {

     
    

mw = new MainWindow(this);

         
      

连接();

             
        

}

      
    
  

这里是Mainwindow的构造函数,它对calculateAverageScore的makding调用,它正在使用ConnectionAndQueries执行查询。由于到目前为止还没有调用connect(),因此connection和statement为null。因此得到空指针异常。

尝试在mw = new MainWindow(this)之前调用connect();言。

  

public ConnectionAndQueries()抛出ClassNotFoundException,SQLException {

     
    

连接();

         
      

mw = new MainWindow(this);

             
        

}

      
    
  

但是,确保Gorkamorka建议的代码重构是必需的。

答案 2 :(得分:1)

看起来您的ConnectionAndQuery对象为空。

我会在构造时检查这是否为零,而不是在你尝试使用它时。这将更早地捕获错误(并且在更有用的时间)。这也是可能的(因为错误报告不清楚 - 见下文):

catch (Exception e) {
    System.out.println("Connecting to the database failed");
}

正在捕获错误,但保留语句对象未初始化(null)。我会检查语句的nullness作为前提条件,或者更好地仍然抛出该原始异常,以便客户端代码必须处理损坏的ConnectionAndQuery对象。

System.out.println(e.getStackTrace().toString());

不是很有帮助,顺便说一下。我宁愿这样做:

e.printStackTrace();

因为它将转储完整的堆栈跟踪,并将其转储到stderr(传统的错误目标)。目前你正在堆栈帧数组上调用toString(),这实际上没有任何用处。