エラーがスローされないように、以下のコードを修正する方法を教えてください。
次のコード行では、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>