- PR -

再帰呼び出し機能

1
投稿者投稿内容
striver
会議室デビュー日: 2004/12/03
投稿数: 15
投稿日時: 2004-12-03 17:56
JSPでBBSシステムを現在開発しているですけど、DBにあるデータ
を一覧リストに表示させるために、ちょっと困っています。
例えばある親データが有って、そのデータに対して返信がある場合は、
そのデータを表示する際、階層したいです。だいたい下記のようになります。

−−−−−−−−−−−−−−−−−−−−−−−−−−−−−
・親DATA
 ・返信A
  ・返信A1
 ・返信B
   ・返信B1
    ・返信B2
−−−−−−−−−−−−−−−−−−−−−−−−−−−−−

これを実現するために、下記のようにループコードを何回か
入れています。今はDEFAULT値として10回ループさせています。
これを無限大にしたいのですけど、何か良い方法はありますか?
大変助かれます。よろしくお願いいたします。


index2 = rs1.getInt("CHAT_IDNO");
sql2 = "select COUNT(CHAT_PARE) as pare_cnt from QCL_CHAT_MAIN where USED_FLAG=1 and CHAT_PARE=" + index2;
sql2 = sql2 + " and MAIN_IDNO=" + main_idno + " and PROJ_IDNO=" + proj_idno;

rs2 = st2.executeQuery(sql2);
rs2.next();
pare_cnt2 = rs2.getInt("pare_cnt");
rs2.close();

if (pare_cnt2>0) {
sql2 = "select * from QCL_CHAT_MAIN where USED_FLAG=1 and CHAT_PARE=" + index2;
sql2 = sql2 + " and MAIN_IDNO=" + main_idno + " and PROJ_IDNO=" + proj_idno + " order by date_send asc";

rs2 = st2.executeQuery(sql2);

while(rs2.next()){
out.println("<tr bgcolor= '#D7D7D7'>");
out.println("<td nowrap colspan=1>&nbsp;</td>");
out.println("<td nowrap>");
out.println("<div style='text-indent:" + rs2.getInt("chat_leve") * 15 + "px'>");
out.println("<a href='bbs_cont_disp.jsp?chat_idno=" + rs2.getInt("chat_idno") + "&main=" + main_idno + "&proj=" + proj_idno + "' border=0 title='chat query display'>");
out.println(Item_title(rs2.getString("chat_inde")) + "</a>");
out.println("</div>");
out.println("</td>");
out.println("<td nowrap>&nbsp;" + rs2.getString("crea_name") + "</td>");
out.println("<td nowrap align=center>" + Item(rs2.getDate("date_send")) + "</td>");
out.println("</tr>");



//===== LEVEL 3 Setting =======================================
index3 = rs2.getInt("CHAT_IDNO");
sql3 = "select COUNT(CHAT_PARE) as pare_cnt from QCL_CHAT_MAIN where USED_FLAG=1 and CHAT_PARE=" + index3;
sql3 = sql3 + " and MAIN_IDNO=" + main_idno + " and PROJ_IDNO=" + proj_idno;
rs3 = st3.executeQuery(sql3);
rs3.next();
pare_cnt3 = rs3.getInt("pare_cnt");
rs3.close();

if (pare_cnt3>0) {
sql3 = "select * from QCL_CHAT_MAIN where USED_FLAG=1 and CHAT_PARE=" + index3;
sql3 = sql3 + " and MAIN_IDNO=" + main_idno + " and PROJ_IDNO=" + proj_idno + " order by date_send asc";

rs3 = st3.executeQuery(sql3);

while(rs3.next()){
out.println("<tr bgcolor= '#D7D7D7'>");
out.println("<td nowrap colspan=1>&nbsp;</td>");
out.println("<td nowrap>");
out.println("<div style='text-indent:" + rs3.getInt("chat_leve") * 15 + "px'>");
out.println("<a href='bbs_cont_disp.jsp?chat_idno=" + rs3.getInt("chat_idno") + "&main=" + main_idno + "&proj=" + proj_idno + "' border=0 title='chat query display'>");
out.println(Item_title(rs3.getString("chat_inde")) + "</a>");
out.println("</div>");
out.println("</td>");
out.println("<td nowrap>&nbsp;" + rs3.getString("crea_name") + "</td>");
out.println("<td nowrap align=center>" + Item(rs3.getDate("date_send")) + "</td>");
out.println("</tr>");



//===== LEVEL 4 Setting ============================
index4 = rs3.getInt("CHAT_IDNO");
sql4 = "select COUNT(CHAT_PARE) as pare_cnt from QCL_CHAT_MAIN where USED_FLAG=1 and CHAT_PARE=" + index4;
sql4 = sql4 + " and MAIN_IDNO=" + main_idno + " and PROJ_IDNO=" + proj_idno;
rs4 = st4.executeQuery(sql4);
rs4.next();
pare_cnt4 = rs4.getInt("pare_cnt");
rs4.close();

if (pare_cnt4>0) {
sql4 = "select * from QCL_CHAT_MAIN where USED_FLAG=1 and CHAT_PARE=" + index4;
sql4 = sql4 + " and MAIN_IDNO=" + main_idno + " and PROJ_IDNO=" + proj_idno + " order by date_send asc";

rs4 = st4.executeQuery(sql4);

while(rs4.next()){
out.println("<tr bgcolor= '#D7D7D7'>");
out.println("<td nowrap colspan=1>&nbsp;</td>");
out.println("<td nowrap>");
out.println("<div style='text-indent:" + rs4.getInt("chat_leve") * 15 + "px'>");
out.println("<a href='bbs_cont_disp.jsp?chat_idno=" + rs4.getInt("chat_idno") + "&main=" + main_idno + "&proj=" + proj_idno + "' border=0 title='chat query display'>");
out.println(Item_title(rs4.getString("chat_inde")) + "</a>");
out.println("</div>");
out.println("</td>");
out.println("<td nowrap>&nbsp;" + rs4.getString("crea_name") + "</td>");
out.println("<td nowrap align=center>" + Item(rs4.getDate("date_send")) + "</td>");
out.println("</tr>");
キルシェ
常連さん
会議室デビュー日: 2004/03/25
投稿数: 26
投稿日時: 2004-12-04 17:54
たぶんコードは、階層毎にSQLを投げてデータを取る処理だと思いますが、
(あまり詳しく見ていません毎回、直接RDBからデータを取るのではなく、
必要なデータを一旦二分木で作ってしまって、そこから切り出す方法は
どうでしょうか。

RDBのレコード
 ↓↑(SQL文)
二分木(投稿/返信データ) … JavaBeansとかでしょうか?
 ↓↑
JSPで表示

という感じです。
ただ、二分木のデータ取得を一部分だけにするなど効率化の方法を
よく考えておかないと、データが増えたときにメモリ圧迫や性能問題が
でるかもしれませんね。

実用性が求められないプログラムであれば、毎回RDBにアクセスしても良いので、
階層ごとのコード記述ではなく、任意の階層のデータを取得できるメソッドと
して定義して、再帰的に呼び出しても良いかもしれませんね。


データの扱われ方(JSPからのアクセスパターン)と、データを格納する際の
特色(RDBのアクセスパターン)は、直接は相容れないので、その間に機能的な
バッファ(例では二分木のオブジェクト)を入れると考えやすいと思います。
striver
会議室デビュー日: 2004/12/03
投稿数: 15
投稿日時: 2004-12-06 19:09
キルシェさん
ご回答ありがとうございます。
確かに今の私の作り方は直接RDBからデータを
取得しています。キルシェさんの下記のパターン
は前にも実際にやったのです。JavaBeansで作って
実行したあと、FREEZEしてしまったという
現象が発生しました。原因はわからなかったけど、
現在は運用しているの今はこれを再現するのは怖いです。
再帰呼び出し機能はjsp:includeで可能でしょうか?
分かる方がいらしゃいましたら是非教えてください。
よろしくお願いいたします。

RDBのレコード
 ↓↑(SQL文)
二分木(投稿/返信データ) … JavaBeansとかでしょうか?
 ↓↑
JSPで表示
キルシェ
常連さん
会議室デビュー日: 2004/03/25
投稿数: 26
投稿日時: 2004-12-07 22:04
すでに試してらしたのですね(^_^;;

使える時間次第だと思いますが、JavaBeansで作成した際の
freezeの原因は追求しておいたほうが良いと思います。
#簡単に考えると、デッドロックか無限ループなのではないかと思います。
#そうではなく、コンテナ周りの設定が原因だと、調べるのが面倒そうですが(^_^;
#いずれにせよ、検証環境がほしいところですが・・・。

それから、求めていポイントはどういった点でしょうか?
・固定数のフォローアップから、任意の回数を実現したい(機能面の改善)
・表示に時間がかかる

前者の任意回数(無限回数)へのフォローアップできる仕組みが目標であれば、
(コネクションを渡して←必須ではありません)特定の一件を得るメソッドだけ
あればよいと思います。この仕組みだけなら、スクリプトレットだけでもできますし、
(コードやincludeの仕方などは)かなりスマートに作れると思います。
後者も対象でしたら、対象となるレコードの一括取得も考える必要が
あると思いますので、ざっくり取得したレコード群から必要部分のみ取捨選択を
行う処理(表示件数分をきちんと取ることができれば不要です)などが
入ると思います。
#結構見た目が複雑になると思います。

いずれにせよ、JSPで表示する表示形式と、データベースに格納する
レコードを整理し、間を取り持つ方法を固めていく必要があると思います。
それなりに、時間はかかると思いますが・・・。
影フリー
常連さん
会議室デビュー日: 2004/11/12
投稿数: 39
お住まい・勤務地: 東京都
投稿日時: 2004-12-08 09:35
以前、勉強のためBBSシステムを作ったことがあります。
以下のURLはそのシステムで動いてます。ソースもまるごと・・
テスト用として試しても構いませんのでご参考になってください。

http://www.kico.co.jp/jforum/door.do?act=SERVLET.BOARD_VIEW&boardname=BOARD_SOURCE_TBL&seq=3
だーやん
会議室デビュー日: 2004/03/07
投稿数: 16
投稿日時: 2004-12-08 22:52
JSPでの再起呼び出し方法はわかりませんが、ループとListを使えば再起と同様のことができます。
あまりよい方法とは思いませんが…。以下のような感じでどうでしょう。

//
List list = new LinkedList();
Resultset resultset = statement.execQuery(親記事を取得するSQL);
list.add(0,result);

while(list.size != 0){
ResultSet rs = (Resultset)list.get(0);
if(!rs.next){
list.remove(0);
continue;
}
/*
* 記事の表示処理
*/

/*
* 返信の件数取得 -> count
*/
if (count > 0) {
Resultset new_rs = new_st.execQuery(返信記事を取得するSQL);
list.add(0,result);
}
}
会議室デビュー日: 2004/10/12
投稿数: 14
投稿日時: 2004-12-09 11:23

JSPにはメソッドが作れます。

メソッドがあれば再帰はわかりやすくなると思います。
または、自分で再帰する直前にスタックして状態を維持するしかないと思います。

JSPは最終的にはHttpJspBaseを継承したJavaのクラスに変換されます。
当然、クラスなのでメソッドなどもあります。

方法は、JSP中に以下のような感じで「<%!」から始まるとそこは
クラスのスコープ内なので自由にコーディングができます。
---[test.jsp]----------------------------------------------
<%!

/**
* 変数も
*/
private String valA="abc";
private static String valB="ABC";


/**
* メソッドも
*/
public String testMethod(){
return valA+valB;
}
%>
<html>
<body>
Hello JavaMethod<br>
<%=testMethod() %>
</body>
</html>
-----------------------------------------------------------

このJSPがJavaのクラスになると以下のようになります。
(あくまで、イメージなので実際はもっと複雑になります。)
---[test.java]---------------------------------------------

public final class test_jsp extends HttpJspBase{

/**
* 変数も
*/
private String valA="abc";
private static String valB="ABC";


/**
* メソッドも
*/
public String testMethod(){
return valA+valB;
}



public void _jspService(HttpServletRequest request, HttpServletResponse response)
throws java.io.IOException, ServletException {
//HTMLの出力などをします。

out.write("<html>\r\n");
out.write("<body>\r\n");
out.write("Hello JavaMethod<br>\r\n");
out.write( testMethod() + "\r\n");
out.write("</body>\r\n");
out.write("</html>\r\n");
}
}
-----------------------------------------------------------
1

スキルアップ/キャリアアップ(JOB@IT)