プロが教える店舗&オフィスのセキュリティ対策術

度重なる質問申し訳ありません。
現在DB操作について学んでいるJava独学者です。

下記のようなソースで一覧表示画面を作成してみました。
この一覧画面をページング処理したいのですが、その方法がよく分からず頭を抱えています。


期待する結果は以下の通りです。
(1)DBの内容を10件ごとに表示し、「Back」「Next」のリンクを使って画面を移動する。
(2)次(もしくは前)に表示する10件がない場合は上記のリンクを非表示としたい。

※ちなみにDBはPostgreSQLを使用しております。


下記はソースの一部です。

**Srvlet**
if(button != null && button.equals("一覧")){
target = "/list.jsp";
CList cList = new CList();
List list = cList.list();
request.setAttribute("SELECT", list);
}


**JSP**
<%@page contentType="text/html; charset=Windows-31J" %>
<%@page import="java.util.*" %>
<%@page import="XXXX.bean.Bean" %>
<%@page import="XXXX.service.CList" %>
<%@page import="XXXX.service.Search" %>
<jsp:useBean id="SELECT" class="java.util.ArrayList" scope="request"/>
<HTML>
<HEAD>
//省略//
</HEAD>
<BODY>
<BR>
<%
ArrayList array = (ArrayList)request.getAttribute("SELECT");
for(int i=0 ; i<array.size() ; i++){
Bean bean = (Bean)array.get(i);
%>

<TR>
<TD><INPUT type="radio" name="radio" value="<%= (int)bean.getId() %>" <%=
bean == array.get(0) ? "checked" : ""%>></TD>
<TD><%= (int)bean.getId() %></TD>
<TD><%= (String)bean.getName() %></TD>
<TD><%= (String)bean.getTel() %></TD>
</TR>
<%} %>
</TABLE>
</TD>
</TR>
</TABLE>
</FORM>
</DIV>

<a href="">
<font color="#0000ff"><b>Back</b></font></a>

<a href="">
<font color="#0000ff"><b>Next</b></font></a>


**CList.java**

DBAccess db = new DBAccess();
db.open();

String SQL = "SELECT*FROM LIST ORDER BY ID ASC;";
db.setSql(SQL);
ResultSet rs=db.select();
List list = new ArrayList();

while (rs.next()) {
Bean bean = new Bean();
bean.setId(rs.getInt("ID"));
                  bean.setName(rs.getString("NAME"));
bean.setTel(rs.getString("TEL"));
list.add(bean);
}

rs.close();
db.close();

return list;
}
}


色々調べた結果、SQL文を使う方法とArrayList等に格納する方法があるようですが、
どちらも良く理解出来ませんでした。


勉強不足で申し訳ありませんが、ご教授お願いいたします。

A 回答 (3件)

No.2です。


ページングに必要な情報はNo.1さんの回答でも私の回答でもほぼ同じことが書いてあると思うのですが・・
全件数、表示するページ番号、1ページのに表示する件数です。

今のコードでは上記のどの情報も保持していないですよね?
毎回全件を取得して最初の5件を表示するだけになっています。
今のコードに加えるならば、
<%
ArrayList array = (ArrayList)session.getAttribute("SELECT");
//ページ番号
int pageNo = Integer.parseInt(request.getParameter("pageNo"));
//1ページの件数
int displayNumber = Integer.parseInt(request.getParameter("displayNumber"));

//for(int i=0; i<array.size() ; i++){
for(int start = (pageNumber - 1) * displayNumber, end = start + displayNumber;start < end && start < array.size(); start++){
Bean bean = (Bean)array.get(start);
%>
というような感じにして、break処理はなくします。
#雰囲気で書いているのでおかしいとこもあるかもしれません。

ですが、一般的にはView(JSP)にこのようなロジックを記述するのではなく、
検索時に必要な分だけをListに詰めてViewに返し、ViewではListを全件表示するだけにすると思います。
そうすればsessionを使う必要もなくなります。

既にそうされているかもしれまえせんが、頭の中で考えるだけではなく
必要な情報や処理を絵に書いてみると整理しやすいと思いますよ。
    • good
    • 4

(1)について


PostgreSQLならばLIMI句とOFFSET句を使えばよさそうです。
環境がないので実際に試すことはできないのですが、
SELECT * FROM LIST ORDER BY ID ASC LIMIT 10(1ページの件数) OFFSET 0(読み飛ばす行数);
とすれば最初の10件が取得できると思います。
以降は表示しようとするページ番号によってOFFSET句の値を変更していけばいいのではないでしょうか。

もしくは、ResultSetのabsoluteメソッドを使って表示開始行までカーソルを移動してから
1ページの件数分だけループしてListに追加するようにしてもいいと思います。

(2)について
検索結果の全件数を保持しておけば、現在表示しているページ番号と1ページの件数から
次ページもしくは前ページが存在するかが判断できると思います。
全件数はCOUNT(*) over() などでSQLで取得したり、
ResultSetのlastメソッドを使ってカーソルの最終行に移動してgetRowメソッドで取得することもできます。


初めはいっぺんにやろうとせずに、少しずつ処理を追加していくようにした方がいいと思います。

この回答への補足

お2人のアドバイスを参考にし、DB量もそこまで多くないことから
今回はListで処理を行うことにしました。

あの後に色々自分なりに修正を加えたものが下記のソースになります。

**Srvlet**
if(button != null && button.equals("一覧")){
target = "/list.jsp";
CList cList = new CList();
List list = cList.list();
HttpSession. session=request.getSession();
session.setAttribute("SELECT", list);
}


**JSP**
//省略//
<BODY>
<BR>
<%
ArrayList array = (ArrayList)session.getAttribute("SELECT");
for(int i=0 ; i<array.size() ; i++){
Bean bean = (Bean)array.get(i);
%>

<TR>
<TD><INPUT type="radio" name="radio" value="<%= (int)bean.getId() %>" <%=
bean == array.get(0) ? "checked" : ""%>></TD>
<TD><%= (int)bean.getId() %></TD>
<TD><%= (String)bean.getName() %></TD>
<TD><%= (String)bean.getTel() %></TD>
</TR>
<%
if(i==4){
break;}
%>
<%} %>
</TABLE>
</TD>
</TR>
</TABLE>
</FORM>
</DIV>

<a href="list.jsp?list=1">
<font color="#0000ff"><b>Back</b></font></a>

<a href="list.jsp?list=2">
<font color="#0000ff"><b>Next</b></font></a>


変数iをbreakすることで5件までの表示に成功しました。

また、request をSessionに変更したことで、情報を記憶出来ているとは思うのですが
NEXT・BACKに飛ぶと同じ情報が保持されたままとなっています。
何か前後の情報を格納しないと期待する処理は行われないと思うのですが、
その部分でまた詰まってしまいました・・・。

アドバイス等御座いましたらお願いいたします。

補足日時:2010/12/29 20:17
    • good
    • 0

一般的には、SQLで表示するページ分だけ取得して、


次へ、前へを押下時に、再度ページ分取得だと思います。
Listでやると全件保持したりしてメモリを圧迫するかと思います。

1.検索結果は全部で何件あるか?(COUNT 文)
2.1.の結果が 1 ページに収まるか?収まらないか?
 全件数 / 1ページ表示件数 = ページ数
 今から表示しようとしているページ番号により、「前へ」「次へ」リンクを表示するか判断する。
3.今から表示しようとしているページ番号により、結果を取得する。

select ...
from テーブル名
offset 80 limit 10

※offset は今から表示しようとするページ番号により何件目から表示するか事前に計算しておく。(3ページ目を表示するなら 10 * 3 = 30 など)
limit は1ページに表示する件数。

4.結果を画面表示する。


簡単に書いたので色々と抜けている、間違っていることがあるかもしれませんが
参考程度にしてください。

この回答への補足

アドバイス有難うございます。
SQLで行うページングロジックを把握出来ただけでも大変有り難いです。

今回は情報量もそこまで大きくないので、Listで行うことにしましたが
SQLで行う方法も今後習得出来るよう精進したいと思います!

補足日時:2010/12/29 20:19
    • good
    • 1

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています