1

基本的に、データベースからResultSetを取得する際に問題が発生します。このコードブロックの34行目(?)でエラーが発生しましたが、マークを付けました

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

実行時にnullポインター例外が発生します。これは、以下の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();
}

ただし、この参照は、参照されているオブジェクトがまだ構築されていない(つまり、コンストラクターがまだ完成していない)ときに送信されるため、この時点で参照をnullにすることしかできません。

これをモンキーフィックスする1つの方法は、新しいConnectionAndQueries()の下にあるコンストラクターからメインメソッドにコードを移動することです。ただし、プログラム構造をリファクタリングして、データベース接続と操作を1つ以上の個別のクラスに分離し、UIコードをデータベースコードから分離することを強くお勧めします。

于 2013-01-02T13:24:01.753 に答える
2

問題はコンストラクターが原因です。

public ConnectionAndQueries()は、ClassNotFoundException、SQLException{をスローします

mw = new MainWindow(this);

接続();

}

ここでは、Mainwindowのコンストラクターから、ConnectionAndQueriesを使用してクエリを実行しているcalculateAverageScoreへのmakding呼び出しがあります。これまでconnect()は呼び出されていないため、connectionとstatementはnullです。そのため、nullポインタ例外が発生します。

mw = new MainWindow(this);の前にconnect()を呼び出してみてください。声明。

public ConnectionAndQueries()は、ClassNotFoundException、SQLException{をスローします

接続();

mw = new MainWindow(this);

}

しかし、確かに、Gorkamorkaによって提案されているように、コードのリファクタリングが必要です。

于 2013-01-02T13:49:21.453 に答える
1

ConnectionAndQueryオブジェクトがnullのようです。

これを使用しようとするときではなく、構築時にnullがないかどうかを確認します。これにより、エラーがはるかに早く(そしてはるかに便利なときに)キャプチャされます。(エラー報告が明確ではないため、以下を参照)次のことも可能です。

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

エラーをキャプチャしていますが、ステートメントオブジェクトは初期化されていません(null)。ConnectionAndQuery前提条件としてステートメントのnullをチェックするか、クライアントコードが壊れたオブジェクトを処理する必要があるように、元の例外をスローする方がよいでしょう。

これ

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

ところで、あまり役に立ちません。私はむしろしたい:

e.printStackTrace();

完全なスタックトレースをダンプし、stderr(エラーの従来の宛先)にダンプするためです。現時点ではtoString()、スタックフレームの配列を呼び出していますが、これは実際には何の役にも立ちません。

于 2013-01-02T13:09:52.460 に答える