1

基本上我在从数据库中获取 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

有趣的是,我最后在课堂上使用了完全相同的连接,并且我没有收到任何错误。将语句复制到第一堂课也不起作用,所以我认为它是别的东西。我想这就是我所拥有的,任何帮助表示赞赏:)

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

    //............................
}
4

3 回答 3

3

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

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

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

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

于 2013-01-02T13:24:01.753 回答
2

问题是由于构造函数。

公共 ConnectionAndQueries() 抛出 ClassNotFoundException, SQLException{

mw = new MainWindow(this);

连接();

}

这里来自 Mainwindow 的构造函数,它对 calculateAverageScore 进行了调用,它正在使用 ConnectionAndQueries 执行查询。由于目前未调用 connect(),因此连接和语句为空。所以得到空指针异常。

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

公共 ConnectionAndQueries() 抛出 ClassNotFoundException, SQLException{

连接();

mw = new MainWindow(this);

}

但可以肯定的是,正如 Gorkamorka 所建议的那样,需要进行代码重构。

于 2013-01-02T13:49:21.453 回答
1

看起来你的ConnectionAndQuery对象是空的。

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

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

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

这个

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

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

e.printStackTrace();

因为它会转储完整的堆栈跟踪,并将其转储到stderr(错误的常规目的地)。目前您正在调用toString()堆栈帧数组,但这并没有真正做任何有用的事情。

于 2013-01-02T13:09:52.460 回答