3

私はJSPとサーブレットを学ぶのは初めてです。ストアドプロシージャを呼び出し、データベースから状態のリストを返すJavaクラスがあります(これは学習中のテストケースですが、他のより複雑なアクションは後で実行されます)。状態のリストは、フォームなどで表示/使用するためにJSPに返される必要があります...今のところ、JSPページを介してデータを印刷し、そこにあることを確認できてうれしいです。

ただし、JSPからJavaコードを呼び出すと、結果オブジェクトがnullとして返されるため、データにアクセスできないように見えます。ResultSetオブジェクトとしてデータを返そうとしましたが、結果は同じです。SQLから呼び出されたときにストアドプロシージャが機能することは知っています。さらに、doPostリクエストに応答し、正常に動作するサーブレットとしてJavaコードがあります...

何が欠けている/理解できないのでしょうか?これは可能ですか?

package edu.XXXX.ais.userapp;

import java.sql.*;
import java.util.*;

public class DBQueries {

    public static Vector<String> getStatesList() {
        Vector<String> results = new Vector<String>();
        Connection con = null;  
        try {

            // Example of executing a stored procedure
            Class.forName("com.mysql.jdbc.Driver");
            con = DriverManager.getConnection ("jdbc:mysql://hostname:3306/dbName","username","password");
            CallableStatement cs = con.prepareCall("{call getStatesList()}");
            ResultSet rs = cs.getResultSet();

            while (rs.next()) {
                results.add(rs.getString(1));
            }
        } catch (SQLException e) {
            System.err.println("Servlet could not display records." + e);

        } catch (ClassNotFoundException e) {
            System.err.println("JDBC driver not found." + e);

        } finally {
            try {
                if (con != null) {
                    con.close();
                    con = null;
                }

            } catch (SQLException e) {
                System.err.println(e);
            }
        }
        return results;
    }
}

上記のJavaコードを呼び出すJSPページ(結果を受信できることを期待しています...)

<html>
<head>
<title>Foo</title>
</head>

<body>
<h3>List of states via a servlet call to the database</h3>
<%@ page import="java.util.*" %>
<%@ page import="edu.XXXX.ais.userapp.DBQueries" %>

<%
    Vector rs = DBQueries.getStatesList();
    if (rs != null)
        for (int index = 0; index < rs.size(); index++) {
            out.println("Name : " + (String) rs.get(index));
        }
%>

</body>
</html>

結果として生じるTomcatエラーは次のとおりです。

org.apache.jasper.JasperException: An exception occurred processing JSP page /states.jsp at line 12

9: <%@ page import="edu.XXXX.ais.userapp.DBQueries" %>
10: 
11: <%
12:     Vector rs = DBQueries.getStatesList();
13:     if (rs != null)
14:         for (int index = 0; index < rs.size(); index++) {
15:             out.println("Name : " + (String) rs.get(index));


Stacktrace:
    org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:568)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:470)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
root cause

java.lang.NullPointerException
    edu.XXXX.ais.userapp.DBQueries.getStatesList(Unknown Source)
    org.apache.jsp.states_jsp._jspService(states_jsp.java:75)
    org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
    org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
    org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
    org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
4

4 に答える 4

5

例外は、どこを見ればよいかを示しています。

edu.XXXX.ais.userapp.DBQueries.getStatesList(Unknown Source)

そのメソッドには null 参照があります。JSP なしでテストし、デバッガーを使用することをお勧めします。

Statementまたはを閉じませんResultSet。それは悲しみにつながります。と同じように、作成とは逆の順序でそれらを閉じますConnection

まず、スクリプトレット コードを JSP に入れるのをやめてください。それが 1999 年のスタイルです。しないでください。

正しいことは、JSTL を学習し、JSP に表示タスクのみを実行させることです。

JSP がサーブレットと対話し、サーブレットに代わってデータベースに介入します。

アプリ サーバーを使用して、データ ソースを設定します。コード内に接続情報を含めないでください。

今のところ、サーブレットと JSP のことは忘れてください。データ層から始めます。

POJO を使用して記述し、テストし、動作させて、脇に置きます。

次に、HTTP 要求を受け取り、パラメーターを検証してバインドし、データ アクセス レイヤーを使用してデータベースと通信し、応答を要求またはセッション スコープに入れてページを表示するサーブレットを作成します。

モデル 2 MVC と呼ばれます。これが Java Web アプリを作成する方法です。

その DBUtils クラスを次のように記述します。

package edu.XXXX.ais.userapp;

import java.sql.*;
import java.util.*;

public class DBQueries {

    public static List<String> getStates(Connection connection) throws SQLException {
        List<String> states = new ArrayList<String>();
        CallableStatement cs = null;
        ResultSet rs = null;
        try {
            cs = connection.prepareCall("{call getStatesList()}");
            boolean hasResultSet = cs.execute();
            rs = cs.getResultSet();    
            while (rs.next()) {
                states.add(rs.getString(1));
            }
        } finally {
            close(rs);
            close(cs);
        }
        return states;
    }

    public static void close(ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void close(Statement st) {
        try {
            if (st != null) {
                st.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public static void close(Connection conn) {
        try {
            if (conn != null) {
                conn.close();
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

DBQuery が機能することを証明する JUnit テストを作成します。

package edu.XXX.ais.userapp;

public class DBQueriesTest {

    // You have to initialize this; I'm deliberately leaving out some details.
    private Connection connection;

    @Test
    public void testGetStates() {
        List<String> actual = DbQueries.getStates(this.connection);
        List<String> expected = { "CT", "NY" };  // whatever
        Assert.assertEquals(expected, actual);
    }
}
于 2012-06-19T23:53:56.717 に答える
2

サンプルコードでは、CallableStatementは前cs.getResultSet()に実行されないため、rsnullになり、NullPointerException実行時に発生しますrs.next()

CallableStatement cs = con.prepareCall("{call getStatesList()}");
boolean bIsResultSetOrNot = cs.execute (); // <-- missed
ResultSet rs = cs.getResultSet(); 

ステートメントが実行されていることを確認し、実行結果がResultSet更新カウントではないことを確認してください。

于 2012-06-20T00:58:39.257 に答える
0

例外スタック トレースは、メソッド DBQueries.getStatesList() にヌル ポインターがあることを示しています。メソッド内の try ブロックを Exception で囲み、それをスローしている行を確認してください。私の推測では、接続オブジェクトは null です。

その場合は、接続の取得中に渡す「ホスト名」の値を確認してください。

于 2012-06-19T23:57:14.250 に答える
0

あなたは文字列のベクトルをベクトルに渡そうとしています。あなたの方法はVector<String> getStatesList()、参照を作成していることNULLです。

../Apache Tomcat/webapps/work に、JSP でコンパイルされたクラスを見つけます。JSP のこれらの行のエラーを見てください。

Spring Core JDBCTemplate クラスを使用してデータベースに接続してください。接続を閉じるのを忘れてしまった場合に非常に便利なクラスです。:) 良い

于 2012-06-20T00:04:23.543 に答える