0

次のサーブレット スニペット:

ResultSet set = statement.executeQuery();
       // userName = set.getString(1);
        if(set.next()) {
            userName = set.getString("FirstName");
            Email = set.getString("Email");
        }
        if(set.wasNull()) {  //<<------------- line 33
            // turn to the error page
            response.sendRedirect("LoginFailure.jsp");
        } else {
            // start the session and take to his homepage
            HttpSession session = request.getSession();
            session.setAttribute("UserName", userName);
            session.setMaxInactiveInterval(900); // If the request doesn't come withing 900 seconds the server will invalidate the session
            RequestDispatcher rd = request.getRequestDispatcher("portfolio_one.jsp");
            rd.forward(request, response); // forward to the user home-page
        }

次の例外を作成します。

INFO: java.sql.SQLException: Invalid operation: wasNull() called with no data retrieved.
at org.apache.derby.client.am.SQLExceptionFactory40.getSQLException(Unknown Source)
at org.apache.derby.client.am.SqlException.getSQLException(Unknown Source)
at org.apache.derby.client.am.ResultSet.wasNull(Unknown Source)
at com.sun.gjc.spi.base.ResultSetWrapper.wasNull(ResultSetWrapper.java:141)
--------->> at projectcodes.ValidateDataForSignIn.doPost(ValidateDataForSignIn.java:33)
    ..........

なぜこの例外が発生するのですか? 強調表示された行が原因で例外が発生します: 33

4

1 に答える 1

4

この例外は、ResultSet#next()が を返したときに発生する可能性がありますfalse。つまり、行がまったくないため、列がまったく取得されていません。はResultSet#wasNull()、最後に取得された行ではなく、最後に取得された列にのみ適用されます。

コード ロジックを再配置する必要があります。

    if(set.next()) {
        userName = set.getString("FirstName");
        Email = set.getString("Email");

        // start the session and take to his homepage
        HttpSession session = request.getSession();
        session.setAttribute("UserName", userName);
        session.setMaxInactiveInterval(900); // If the request doesn't come withing 900 seconds the server will invalidate the session
        RequestDispatcher rd = request.getRequestDispatcher("portfolio_one.jsp");
        rd.forward(request, response); // forward to the user home-page
    } else {
        // turn to the error page
        response.sendRedirect("LoginFailure.jsp");
    }

より明確なのは、JDBC の混乱をすべてスタンドアロンのUserDAODAO クラスにリファクタリングし、Userモデル クラスを次のように使用することです。

User user = userDAO.find(username, password);

if (user != null) {
    request.getSession().setAttribute("user", user);
    request.getRequestDispatcher("portfolio_one.jsp").forward(request, response);
} else {
    response.sendRedirect("LoginFailure.jsp");
}

メソッドは次のfind()ようになります。

public User find(String username, String password) throws SQLException {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    User user = null;

    try {
        connection = database.getConnection();
        statement = connection.prepareStatement("SELECT id, username, email, firstname, lastname, FROM user WHERE username = ? AND password = MD5(?)");
        statement.setString(1, username);
        statement.setString(2, password);
        resultSet = statement.executeQuery();

        if (resultSet.next()) {
            user = new User();
            user.setId(resultSet.getLong("id"));
            user.setUsername(resultSet.getString("username"));
            user.setEmail(resultSet.getString("email"));
            user.setFirstname(resultSet.getString("firstname"));
            user.setLastname(resultSet.getString("lastname"));
        }
    } finally {
        close(resultSet, statement, connection);
    }

    return user;
}

このようにして、より自己文書化され、より再利用可能/テスト可能なコードになります。

以下も参照してください。

于 2012-04-24T17:11:13.397 に答える