1

エラーがスローされないように、以下のコードを修正する方法を教えてください。

次のコード行では、null ポインター例外が発生しています。

return dataSource.getConnection();

dataSource は、web.xml で指定された javax.sql.DataSource のインスタンスであり、他のコードによって呼び出されたときに正常に動作することに注意してください。

null ポインターが発生している DataAccessObject.java の実際のメソッドを次に示します。

protected static Connection getConnection(){  
  try {
     return dataSource.getConnection();  //
  } catch (SQLException e) {
     throw new RuntimeException(e);
  }
}

前のメソッドは、次のコード行によって呼び出されています。

connection = getConnection();  

これは、次のように CourseSummaryDAO というクラスの次のメソッドにあります。

public List<CourseSummary> findAll(Long sid) {
    LinkedList<CourseSummary> coursesummaries = new LinkedList<CourseSummary>();
    ResultSet rs = null;
    PreparedStatement statement = null;
    Connection connection = null;
    try {
        connection = getConnection(); //
        String sql = "select * from coursetotals where spid=?";
        statement = connection.prepareStatement(sql);
        statement.setLong(1, sid);
        rs = statement.executeQuery();
        //for every row, call read method to extract column 
        //values and place them in a coursesummary instance
        while (rs.next()) {
            CourseSummary coursesummary = read("findAll", rs);
            coursesummaries.add(coursesummary);
        }
        return coursesummaries;
     }catch (SQLException e) {
        throw new RuntimeException(e);
     } 
     finally {
        close(rs, statement, connection);
    }
 }  

これを簡単に再現するために、次の TestCourseSummaries クラスを作成しました。

public class TestCourseSummaries {
    public static void main(String[] args) {
    Long id = new Long(1002);
    CourseSummaryDAO myCSDAO = new CourseSummaryDAO();
    List<CourseSummary> coursesummaries = myCSDAO.findAll(id);
    for(int i = 0;i<coursesummaries.size();i++){
    System.out.println("type, numunits are: "+coursesummaries.get(i).getCourseType()+","+coursesummaries.get(i).getNumUnits());
    }
}
}  

編集:

JustDanyul さんの質問に答えるために、アプリケーションで呼び出すコードと、呼び出しコード内の 2 つの DAO オブジェクトによって拡張される基になる DataAccessObject コードを囲んでいます。

これは、エラーをトリガーするアプリケーションのコードです。それぞれが DataAccessObject を拡張した 2 つのクラスがあることを確認してください。おそらく、それらは互いに競合しているため、2 番目のものはデータベース接続を取得できませんか?

protected void doGet(HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException {  
   String idString = req.getParameter("id");
   Long id = new Long(idString);
   ThisObj thisobj = new ThisDAO().find(id);
   req.setAttribute("thisobj", thisobj);
   ThoseObjDAO myThoseDAO = new ThoseObjDAO();
   List<ThoseObj> thoseobjects = myThoseObjDAO.findAll(id);
   req.setAttribute("thoseobjects", thoseobjects);
   jsp.forward(req, resp);

}

そして、呼び出しコードの 2 つの DAO クラスによって拡張された DataAccessObject クラスのコードを次に示します。

public class DataAccessObject {
private static DataSource dataSource;
private static Object idLock = new Object();

public static void setDataSource(DataSource dataSource) {
   DataAccessObject.dataSource = dataSource;
}

protected static Connection getConnection() {
   try {return dataSource.getConnection();}
   catch (SQLException e) {throw new RuntimeException(e);}
}

protected static void close(Statement statement, Connection connection) {
   close(null, statement, connection);
}

protected static void close(ResultSet rs, Statement statement, Connection connection) {
   try {
      if (rs != null) rs.close();
      if (statement != null) statement.close();
      if (connection != null) connection.close();
   } catch (SQLException e) {throw new RuntimeException(e);}
}

protected static Long getUniqueId() {
   ResultSet rs = null;
   PreparedStatement statement = null;
   Connection connection = null;
   try {
      connection = getConnection();
      synchronized (idLock) {
         statement = connection.prepareStatement("select next_value from sequence");
         rs = statement.executeQuery();
         rs.first();
         long id = rs.getLong(1);
         statement.close();
         statement = connection.prepareStatement("update sequence set next_value = ?");
         statement.setLong(1, id + 1);
         statement.executeUpdate();
         statement.close();
         return new Long(id);
      }
   }
   catch (SQLException e) {throw new RuntimeException(e);}
   finally{close(rs, statement, connection);}
}
}  

データ ソースは、次のように web.xml に作成されます。

<resource-ref>
    <description>dataSource</description>
    <res-ref-name>datasource</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>
4

3 に答える 3

1

「正常に実行される」コードは、実際にアプリケーションサーバーで実行されているコードであると思われます。メソッドを実行するだけの投稿している例ではstatic void main()、web.xml で定義されているリソースを取得できません。

JDNI を使用して初期データソースをセットアップしていると思います。そして、次のようなものを使用して

@Resource(name="jdbc/mydb")
private DataSource dataSource;

接続をセットアップします。右?

編集:

あなたのコードを見た後、あなたのデータソースはまったく新しく初期化されたようです。要素を web.xml に入れるだけでは、それだけではできません。また、実際に dataSource を構成する必要があります。ドライバー、ユーザー名、パスワード、URI などを指定します。

機能するDAOのfind()メソッドは、実際にはdataSourceを使用していないと思います。これまでに示したものは、初期化された dataSource があることをまったく示していません。

アイデアを提供するために、Tomcat と JDNI を使用してこれを行う方法についてのチュートリアルが気に入りました。(またはさらに良いことに、spring-jdbc を使用します)。

http://www.mkyong.com/tomcat/how-to-configure-mysql-datasource-in-tomcat-6/

于 2013-08-10T00:36:43.963 に答える
1

<javax.sql.DataSource>のインスタンスではなく、インスタンスとして dataSource を使用します<javax.activation.DataSource>

つまり、ステートメント<import javax.activation.DataSource;>をこの otherに置き換える必要があります<import javax.sql.DataSource;>

于 2013-11-08T00:13:32.793 に答える