mb_language("uni"); mb_internal_encoding("utf-8"); mb_http_input("auto"); mb_http_output("utf-8"); ?>
前々回、前回とアイテム情報を表示する画面を作成しました。Xprioriからデータを取得しWebページとして表示するまでの簡単な流れを理解していただけたのではないでしょうか。今回と次回はアイテムの登録/編集/削除機能の実装を紹介します。情報入力画面、内容確認画面の実装を通して、Xprioriにデータ投入する流れを理解していただければと思います。今回作成する画面は以下のような機能をもっています。
● 情報入力画面
新規アイテムや登録済みアイテムの内容を編集する画面です。以下の機能を持っています。
1. アイテム情報入力(今回)
2. 編集の場合、アイテム詳細表示画面で選択した編集するアイテムの情報を表示する。(次回)
● 内容確認画面
アイテム情報の登録/削除確認を行う画面です。以下の機能を持っています。
1. 登録/編集の場合、入力画面で入力した内容を確認表示(今回)
2. 編集後の入力値のチェック(次回)
3. 入力チェック後のXprioriへのアイテムの登録/更新/削除(今回は登録のみ)
4. 削除の場合、アイテム詳細表示画面で選択した削除するアイテムの情報を表示(次回)
アイテム登録のために作成するクラスを紹介します。
クラス名 |
概要 |
アイテム更新クラス (UpdateAddressbookBean) |
アイテムを登録/編集/削除するクエリーをXprioriに送信するクラス |
情報入力画面に入力フォームを作成し、アイテムの名前、郵便番号、住所を入力できるようにします。新規アイテムのIDは、現在登録されているIDの最大値に+1したものを自動的に割り振り、ユーザが入力できないようにします。
SearchAddressbookBeanクラスに下記の関数を追加します。
● 新規アイテム用のIDを取得する関数(getNewId)
登録されているアイテムIDの最大値に+1したIDを返す関数です。IDの最大値を取得するためXprioriに問い合わせるXPathは、
max(/ND/address_book/item/@id) |
となります。なおXPathで使用しているmax()は、引数で指定したXPathが取得したノード集合の最大値を返すXPathの関数です。
public String getNewId() { // IDの最大値を取得するXPath String xpath = "max(/ND/address_book/item/@id)"; // 検索結果を取得する String tmpItem_xml = xcon.query(xpath); // XMLを解析する Document doc = AddressbookUtils.loadXMLFromString(tmpItem_xml); // 最大値に+1する int newIntId = AddressbookUtils.getQResultInteger(doc) + 1; // idの形式に整形する String newStrId = String.format("%06d", newIntId); return newStrId; } |
入力画面で入力したアイテム情報はGETパラメータで確認画面に渡されるので、ParamBeanクラスを拡張し、アイテム情報の設定/取得ができるようにします。また、新規か編集か削除かを判断するパラメータとしてmodeの設定/取得もできるように拡張します。
さらに、ParamBeanが持つアイテム情報からItemBeanを作成できるようにSearchAddressbookBeanにgetItemByParam関数を追加します。
public ItemBean getItemByParam(ParamBean param) { ItemBean item = new ItemBean(); // パラメータの情報をアイテムに設定する item.setID(param.getId()); item.setName(param.getName()); item.setZip(param.getZip()); item.setAddress(param.getAddress()); return item; } |
確認画面で問題がない場合、実行ボタンを押しアイテムを登録するため、UpdateAddressbookBeanクラスを作成します。UpdateAddressbookBeanはConnectXprioriBeanやItemBeanを組み合わせ、Xprioriに接続しアイテムを挿入/編集/削除するクラスです。以下の関数を持っています。
● アイテムを挿入する(insertItem)
insertItem関数には挿入するItemBeanクラスを引数に渡しますが、ItemBeanクラスはそのままではXprioriに登録することができないので、Xprioriに登録するためのXMLを取得するgetItemXML関数をItemBeanクラスに追加します。
public String getItemXML() { String itemXML = "<item id=\"" + this.getID() + "\">" + "<name>" + this.getName() + "</name>" + "<zip>" + this.getZip() + "</zip>" + "<address>" + this.getAddress() + "</address>" + "</item>"; return itemXML; } |
その後、ItemBeanクラスのgetItemXML関数を利用して取得したXMLをXprioriに登録されているitem要素の最後に挿入します。このとき、item要素が全て削除されている場合も考えられるので、その場合はaddress_book要素の最初の子要素であるdummy要素の下に挿入します。なお、このdummy要素とはユーザには見えない要素です。
public String insertItem(ItemBean item) { // Xprioriに登録されている最後のitem要素を指定するXPath String insertXPath = "/ND/address_book/item[last()]"; //最後のitem要素が存在するかチェックする String tmpItem_xml = xcon.query(insertXPath); Document doc = AddressbookUtils.loadXMLFromString(tmpItem_xml); // item要素が存在しないときはaddress_book要素の最初の子要素である // dummy要素を挿入対象要素とする if(doc.getElementsByTagName("item").item(0) == null){ insertXPath = "/ND/address_book/dummy[last()]"; } // itemから挿入用XMLを作り、そのXMLを挿入する String ret = xcon.insert(insertXPath, item.getItemXML()); return ret; } |
挿入の実行にはConnectXprioriBeanクラスのinsert関数を利用します。insert関数はAPIのinsertXML関数をラップした関数であり、引数に挿入する位置を指定するためのXPathと挿入するXMLを渡します。挿入する位置を指定するXPathは、item要素が既に1つ以上存在する場合は
/ND/address_book/item[last()] |
item要素が1つも存在しない場合は
/ND/address_book/dummy[last()] |
です。なおXPathで使用しているlast()は、最後の要素を指定するXPathの関数です。
public String insert(String xpath, String xml) { String ret = ""; try {// queryXMLをラップする ret = neosession.insertXML(xpath, xml); } catch (Exception e) { System.out.println("エラーが発生しました: " + e); } return ret; } |
では、これらのクラスを利用して新規アイテム登録機能を持ったJSPを書いてみます。処理全体の流れは入力画面(iteminput.jsp)→確認画面(itemconfirm.jsp)→登録を実行し一覧画面に戻る(runitem.jsp)となります。ただし、入力値のチェックを確認画面で行い、エラーがあった場合は入力画面に戻るようにします。各画面は以下のようなロジックとなります。なお、入力値のチェックについて(CheckBean)の詳細は次回紹介します。
● 情報入力画面(inputitem.jsp)
使用するクラスはSearchAddressbookBean、ItemBean、ParamBeanです。コードを以下に示します。
<%@ page language="java" contentType="text/html; charset=Shift_JIS" pageEncoding="Shift_JIS"%> <%@page import="addressbook.ItemBean"%> <% request.setCharacterEncoding("Shift_JIS"); %> <jsp:useBean id="searchxpri" class="addressbook.SearchAddressbookBean"></jsp:useBean> <jsp:useBean id="param" class="addressbook.ParamBean"></jsp:useBean> <jsp:setProperty name="param" property="id" param="id" /> <jsp:setProperty name="param" property="name" param="name" /> <jsp:setProperty name="param" property="zip" param="zip" /> <jsp:setProperty name="param" property="address" param="address" /> <jsp:setProperty name="param" property="mode" param="mode" /> <jsp:setProperty name="param" property="errmsg" param="errmsg" /> <% // 入力用アイテムの雛形を定義 ItemBean input_item = new ItemBean(); //(1) 入力エラーで戻ってきてないか判断する if(param.getErrmsg().equals("")){ // パラメータmodeをみて新規追加か既存編集かを決める if(param.getMode() == param.INS_MODE){ // (2-1)新規追加の場合は空のアイテムを作り、IDを割り当てる ItemBean item = new ItemBean(); item.setID(searchxpri.getNewId()); input_item = item; } else if(param.getMode() == param.MOD_MODE){ // 既存編集の場合はパラメータidからアイテムを取得する ItemBean item = searchxpri.getItemById(param.getId()); input_item = item; } } else{ //入力エラー発生時 //(2-2)パラメータからアイテムを作る ItemBean item = searchxpri.getItemByParam(param); input_item = item; } %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <title>アイテム入力</title> </head> <center> <table width="550"><tr><td> <table border="0" cellpadding="0" cellspacing="0" width="100%"> <tr><td ><h3>アイテム情報入力</h3></td></tr> </table> <form action="/address_book/confirmitem.jsp" method="get"> <table width="100%" border="0" cellspacing="0" cellpadding="3"> <%-- 入力エラー発生時にはエラーメッセージを表示する --%> <%if(!param.getErrmsg().equals("")){ %> <tr> <td width="1%" nowrap >入力エラーが発生しました。<%= param.getErrmsg() %></td> <td width="99%" align="right"></td> </tr> <% } %> <tr> <td width="1%" nowrap ></td> <td width="99%" align="right"><a href="/address_book/itemlist.jsp">一覧に戻る</a></td> </tr> </table> <%-- (3)アイテム情報をテキストボックスにいれる --%> <table width="100%" border="1" cellspacing="0" cellpadding="3"> <tr><th>ID</th><td><%= input_item.getID() %></td></tr> <tr><th>名前</th><td><input type="text" name="name" value="<%= input_item.getName() %>"></td></tr> <tr><th>郵便番号</th><td><input type="text" name="zip" value="<%= input_item.getZip() %>"></td></tr> <tr><th>住所</th><td><input type="text" name="address" value="<%= input_item.getAddress()%>" size="80"></td></tr> <tr><td colspan="2" align="center"> <input type="hidden" name="id" value="<%= input_item.getID() %>"> <input type="hidden" name="mode" value="<%= param.getMode() %>"> <input type="submit" value="確認"> </td></tr> </table> </form> </td></tr></table> </center> </body> </html> |
処理の流れを説明します。
(1)確認画面で入力エラーが発生した場合、エラーメッセージがパラメータに含まれるので、それを見て入力エラーかどうかを判断する。
(2-1)パラメータmodeがINS_MODE(値は1)だった場合は、新規追加なので、空のアイテムを作成し、SearchAddressbookBeanクラスのgetNewId関数で取得した新規IDを割り当てる。
(2-2)入力エラーの場合は、前回入力した値がパラメータで渡されるので、入力した値をフォームに再度表示するためにSearchAddressbookBeanクラスのgetItemByParam関数を利用してパラメータからアイテムを作成する。
(3)アイテム情報を入力するためのフォームを作成し、新規の場合は新規アイテムIDを割り当てた空のアイテムの情報を、エラーの場合はパラメータから作成したアイテムの情報を表示する。IDはhidden値に代入する。また、パラメータmodeもhidden値に代入する。
実行結果は以下のようになります。
▲アイテム情報入力画面
● 内容確認画面(confirmitem.jsp)
使用するクラスはSearchAddressbookBean、ItemBean、CheckBean、ParamBeanです。コードを以下に示します。
<%@ page language="java" contentType="text/html; charset=Shift_JIS" pageEncoding="Shift_JIS"%> <%@page import="addressbook.ItemBean"%> <% request.setCharacterEncoding("Shift_JIS"); %> <jsp:useBean id="searchxpri" class="addressbook.SearchAddressbookBean"></jsp:useBean> <jsp:useBean id="param" class="addressbook.ParamBean"></jsp:useBean> <jsp:useBean id="check" class="addressbook.CheckBean"></jsp:useBean> <jsp:setProperty name="param" property="id" param="id" /> <jsp:setProperty name="param" property="name" param="name" /> <jsp:setProperty name="param" property="zip" param="zip" /> <jsp:setProperty name="param" property="address" param="address" /> <jsp:setProperty name="param" property="mode" param="mode" /> <% String msg = "以下の内容でアイテムを登録しますか?"; // 確認メッセージ //確認用アイテムの雛形を定義 ItemBean confirm_item = null; // パラメータmodeをみて新規追加、既存編集か既存削除かを決める if(param.getMode() == param.INS_MODE || param.getMode() == param.MOD_MODE ){ // 新規追加、既存編集の場合 // 入力内容をチェックし、入力エラーの場合は入力画面に戻る(詳細は次回紹介) check.checkItemParam(param); if(check.getErrflg()){//エラーがある場合は入力画面に戻る %> <jsp:forward page="inputitem.jsp"> <jsp:param name="errmsg" value="<%= check.getErrmsg() %>" /> <jsp:param name="id" value="<%= param.getId() %>" /> <jsp:param name="name" value="<%= param.getName() %>" /> <jsp:param name="zip" value="<%= param.getZip() %>" /> <jsp:param name="address" value="<%= param.getAddress() %>" /> <jsp:param name="mode" value="<%= param.getMode() %>" /> </jsp:forward> <% } //(1)パラメータからアイテムを作成する ItemBean item = searchxpri.getItemByParam(param); confirm_item = item; } else if(param.getMode() == param.DEL_MODE){ // 既存削除の場合 ItemBean item = searchxpri.getItemById(param.getId()); confirm_item = item; msg = "以下の内容のアイテムを削除しますか?"; // 確認メッセージ } %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=Shift_JIS"> <title>アイテム内容確認</title> </head> <center> <table width="400"><tr><td> <table border="0" cellpadding="0" cellspacing="0" width="100%"> <tr><td ><h3>アイテム内容確認</h3></td></tr> </table> <%= msg %> <form action="/address_book/runitem.jsp" method="get"> <table width="100%" border="0" cellspacing="0" cellpadding="3"> <tr> <td width="1%" nowrap ></td> <%-- 一覧に戻るときは検索キーワードを渡す --%> <td width="99%" align="right"><a href="javascript:history.go(-1)">前画面に戻る</a></td> </tr> </table> <%--(2)ItemBeanから、アイテム情報を取得し表示する --%> <table width="100%" border="1" cellspacing="0" cellpadding="3"> <tr><th>ID</th><td><%= confirm_item.getID() %></td></tr> <tr><th>名前</th><td><%= confirm_item.getName() %></td></tr> <tr><th>郵便番号</th><td><%= confirm_item.getZip() %></td></tr> <tr><th>住所</th><td><%= confirm_item.getAddress() %></td></tr> <tr><td colspan="2" align="center"> <input type="hidden" name="id" value="<%= confirm_item.getID() %>"> <input type="hidden" name="name" value="<%= confirm_item.getName() %>"> <input type="hidden" name="zip" value="<%= confirm_item.getZip() %>"> <input type="hidden" name="address" value="<%= confirm_item.getAddress() %>"> <input type="hidden" name="mode" value="<%= param.getMode() %>"> <input type="submit" value="実行"> </td></tr> </table> </form> </td></tr></table> </center> </body> </html> |
処理の流れを説明します。
(1)パラメータmodeがINS_MODE(値は1)だった場合は新規追加なので、SearchAddressbookBeanクラスのgetItemByParam関数を利用してパラメータからアイテムを作成する。
(2)パラメータから作成したアイテム情報を表示し、hidden値に代入する。また、パラメータmodeもhidden値に代入する。
実行結果は以下のようになります。
▲アイテム情報確認画面
● アイテム登録実行(runitem.jsp)
runitem.jspは確認画面で実行ボタンが押されたときに遷移し、確認済みのアイテムをXprioriに登録するページです。実行後にアイテム一覧画面に遷移するので、このページをユーザが見ることはありません。
使用するクラスはSearchAddressbookBean、UpdateAddressbookBean、ItemBean、ParamBeanです。コードを以下に示します。
<%@ page language="java" contentType="text/html; charset=Shift_JIS" pageEncoding="Shift_JIS"%> <%@page import="addressbook.ItemBean"%> <% request.setCharacterEncoding("Shift_JIS"); %> <jsp:useBean id="searchxpri" class="addressbook.SearchAddressbookBean"></jsp:useBean> <jsp:useBean id="updatexpri" class="addressbook.UpdateAddressbookBean"></jsp:useBean> <jsp:useBean id="param" class="addressbook.ParamBean"></jsp:useBean> <jsp:setProperty name="param" property="id" param="id" /> <jsp:setProperty name="param" property="name" param="name" /> <jsp:setProperty name="param" property="zip" param="zip" /> <jsp:setProperty name="param" property="address" param="address" /> <jsp:setProperty name="param" property="mode" param="mode" /> <% //(1)パラメータidからアイテムを取得する ItemBean item = searchxpri.getItemById(param.getId()); // パラメータmodeをみて新規追加か既存編集か既存削除かを決める if(param.getMode() == param.INS_MODE ){ // 新規追加の場合 //(2)同一IDを持つアイテムが登録されていないかチェックする if(item.getID().equals("")){//まだ登録されていない //(3)パラメータからアイテムを作成する ItemBean insert_item = searchxpri.getItemByParam(param); //(4)アイテムをXprioriに登録する updatexpri.insertItem(insert_item); } } else if(param.getMode() == param.MOD_MODE){// 既存編集の場合 // 次回実装 } else if(param.getMode() == param.DEL_MODE){ // 既存削除の場合 // 次回実装 } %> <%--(5)処理終了後に一覧ページに戻る --%> <jsp:forward page="itemlist.jsp" > <jsp:param name="sword" value="<%= param.getName() %>" /> </jsp:forward> |
処理の流れを説明します。
(1)SearchAddressbookBeanクラスのgetItemById関数を利用して、パラメータidからアイテムを取得する。
(2)パラメータmodeがINS_MODE(値は1)だった場合は新規追加なので、(1)で取得したアイテムが空かどうかチェックし、このパラメータidと同一のIDを持つアイテムが登録されていないか確認する。
(3)同一IDのアイテムが登録されていない場合は、新規アイテムを登録するためSearchAddressbookBeanクラスのgetItemByParam関数を利用してパラメータからアイテムを作成する。
(4)作成したアイテムをUpdateAddressbookBeanクラスのinsertItem関数を利用してXprioriに登録する。
(5)処理終了後にアイテムの名前を検索キーワードのパラメータswordに渡し、アイテム一覧画面に遷移する。
実行後は一覧画面でアイテムが登録されたことが確認できます。
▲登録されたアイテム
このようにして、アイテム情報入力画面と入力内容確認画面を作成し、新規アイテム登録機能を追加することができました。RDBでは検索/挿入の両方をSQLによるクエリ送信で実行しますが、Xpriori APIのqueryXMLではSQLのINSERT文のような挿入命令を表現することができないので、新規ノードの挿入はinsertXMLというXpriori APIの別の関数を利用することで実行します。挿入の場合、登録する位置をXPathで指定するのもXML DB独特の登録方法といえるでしょう。
次回は入力パラメータのチェック機能の詳細と、アイテムの編集機能と削除機能を追加する部分を紹介します。
今回作成したjavaクラス・jspファイルはこちらからダウンロードすることができます。
・ jspファイルはWebアプリケーションフォルダのaddress_book/WebContentに配置してください。
・ javaファイルはWebアプリケーションフォルダのaddress_book/WebContent/WEB-INF/srcに配置してください。
また、ご自分でクラスを新規作成する場合はEclipseのメニューバーより、[ファイル]→[新規]→[クラス]を選択し、[次へ]を押してください。
次の画面で[ソースフォルダ]に「address_book/src」、[パッケージ]に「addressbook」を入力し、[名前]に適切なクラス名を入力し、[終了]を押すことで、新規のクラスを作成することができます。
▲このページのTOPへ