家計簿を作ろう(初心者編)
http://www.opengion.com/index.php?%E5%AE%B6%E8%A8%88%E7%B0%BF%E3%82%92%E4%BD%9C%E3%82%8D%E3%81%86%28%E5%88%9D%E5%BF%83%E8%80%85%E7%B7%A8%29概要
ここでは、実際に簡単な家計簿システム(といってもまったく大したことはありませんが)を作りながら、openGionをベースとしたWebシステムの作成手順を説明します。
(なんでもそうですが、一度、ざくっとしたイメージさえ掴めれば、後は、リファレンスマニュアルさえあれば、何とかなります)
システムが完成するまでの手順は、以下の通りです。
- はじめに
- DB定義書、画面一覧の作成(設計フェーズ)
- DB定義の読み込み、DB環境の作成(環境構築フェーズ)
- リソースの作成(開発フェーズ)
- 各画面の作成(開発フェーズ)
- 最後に
では、早速1番から開始しましょう!
はじめに †
openGionでは、システムIDという考え方があります。
これは、画面定義や、各項目定義などを行う際の、キーとなる値です。
1システムに対してユニークなIDを割り当てます。
このシステムIDは、大文字で定義しますが、基本的には、コンテキスト名と
同じ、と考えてもらって構いません。
というこで、今回もこの家計簿システムを構築するに当たり、システムIDを決める必要がありますが、KaKeibo?の区切りのいいところの子音を取って、"KK"としたいと思います。
また、コンテキスト名は、"kk"とします。
(開発に当たっては、開発環境を利用することで効率化が図れます。開発環境の構築方法はこちら→インストール(評価環境))
今回作成する家計簿システムは、こちら→
kakeibo.zipからダウンロードすることができます。
[ファイルの内容]
kk - db テーブル及びインデックスを作成するためのSQLスクリプト
- doc DB定義書
- jsp - KK* 画面JSP
- WEB-INF - classes - resource - *.xml
リソースxmlファイル。この場所にxml形式のリソースファイルを
配置することで、初回起動時に自動的にロードされます)
- kk.xml
Tomcatのコンテキスト定義ファイル
apps/tomcatxxxx/conf/tomcat/localhost以下に
コピーして下さい。
DB定義、画面一覧の作成(設計フェーズ) †
今回は、単なる画面作成ではなく、システム作成なので、ここから始まります。(と言っても、外部設計、内部設計などの上流肯定はすっとばしています)
DB一覧 †
まずは、DB定義のDB一覧です。
このシステムでは、単純なお金の収支を管理するだけなので、基本的には
- 口座を管理するための「口座マスタ」
- 収支の項目を管理するための「収支分類マスタ」
の2つで十分です。
但し、この場合だと、月度の範囲の管理(給料日から次の給料日までを区切りとするなど)ができないので、
- 「月度範囲マスタ」
を追加した3つをマスタとして管理します。
なお、手持ち残金は、仮想的な口座として扱い、口座Cを割り当てます。
次にトランザクションですが、これについては、
- 収支の明細を管理するための「収支明細テーブル」
の1つで十分です。
このテーブルでは、いつ、どこの口座から(From)、どこの口座に(To)、どの分類で、いくら+-が発生したか、を管理します。
手持ちも仮想的な口座として管理するので、コンビニで支払った場合などは、Fromが手持ちになるイメージです。
また、全てのテーブルについてですが、ログインユーザー毎に検索・登録できるデータに制限がかけられるように、キー項目として、ユーザーIDを付加します。
DB定義書 †
DB一覧に書き込まれた内容を元に、DB定義書を作成します。
注意点として、ここで作成したDB定義書は、あらかじめ決められたフォーマットで作成する必要があります。
何故なら、このDB定義書を後で、openGionのDB定義システムに取り込みDBスクリプトの作成、リソースの作成を行うからです。
(実際に作成したDB定義書は、こちら→
dbdef.xls)
DB定義書の用語説明 UK - Unique Keyの意。複数カラムがある場合は、1,2・・・と連番を振る Ix - x番目のIndex。複合キーの場合は、1,2・・・と連番を振る Renderer - カラムリソースの表示種別(ここでは詳細説明は省略) Editor - カラムリソースの編集種別(ここでは詳細説明は省略) DBType - カラムリソースの文字種別(ここでは詳細説明は省略)
画面一覧 †
次に画面一覧です。
画面一覧自体には、決められたフォーマットはありませんが、後の「リソース登録」の際に、ここで定義した画面一覧をリソース情報として登録します。
まず、各種マスタに対する画面です。
- 口座マスタ登録画面
- 収支分類マスタ登録画面
- 月度範囲マスタ登録画面
次に、日々の家計簿を登録する画面ですが、これは、収支明細テーブルを登録する画面とイコールになります。
- 収支明細登録画面
さらに、月度の項目別、口座別の収支を確認するための画面が必要にになります。
- 月度集計検索画面
ということで、この5画面があれば、最低下の家計簿としての機能は果たせそうです。
(本来なら、項目単位の月度推移などをグラフで表示する画面などもあったほうがいいのですが、今回は初心者編ということで省略します。)
DB定義の読み込み、DB環境の作成(環境構築フェーズ) †
DB定義の読み込み †
はじめに作成したDB定義書をDB定義システムに登録し、DB環境の構築及びリソース情報の作成を行います。
開発環境(GF)にアクセスし、左フレームに表示されているメニューから、[取り込み・出力] -> [定義ファイル取込] の画面を開きます。
システムIDのところに"KK"と入れた後、検索ボタンを押します。
(※以下の説明で、画面の検索条件に"システムID"が存在する場合は、全て"KK"と入力します。(説明文上からは省略します))
すると、RESULT画面に「取込」ボタンが現れますので、これを押し、先ほどのDB定義書を選択し、取込を行います。
正常に取り込めた場合は、「登録しました」という文字と共に取り込みできた明細が表示されるはずです。
ここまででは、DB定義情報としてはまだ取り込まれていません。
というものの、通常、Excelで管理されているDB定義書は、整合性がとれていないことが多い(同じ項目名で桁数が違うなど)、この状態で、データの整合性のチェックを行った後、DB定義情報として取り込む、という流れになっています。
但し、今回の場合は、あらかじめ整合性をとっているため、チェックの手順を削除して、早速、DB定義情報として取り込みます。
先ほどの下の画面、「定義ファイル検証・反映」の画面を開き、DB定義取込を行うことで、DB定義書情報としての取込が完了します。
取り込まれた情報は、「定義管理」のカテゴリーから、それぞれ、テーブル、テーブルカラム、インデックス、インデックスカラム の画面より確認することができます。
DBスクリプトの作成 †
取り込んだDB定義情報より、テーブルとインデックスのDBスクリプトを生成します。
DBスクリプトは、「取込・出力」 -> 「DBスクリプト作成」画面より行います。
TYPEをHSQLDBに変更して、検索ボタンを押します。
下の画像のようにでればOKです。
(今回は、開発環境と同じHSQLDBのデータベース上に家計簿システムを構築していますが、MySQL等、外部のDBにデータを保存する場合は、そのDBに対応したTYPEを選択することで、各DBのスクリプトを生成することができます)
保存したファイルは、
opengion/uap/webapps/gf/filetemp/admin/(TABLE,INDEX)
に保存されています。
DBスクリプトの実行 †
先ほど作成したDBスクリプトを実行し、DB環境を作成します。
スクリプトの実行は、「管理」 -> 「DB検索」の画面より行います。
各スクリプトの内容を貼り付けた後、検索ボタンを押すことで、DDL文が実行されます。
これで、無事DB環境が構築できました。
(DB環境のを自動でインストールする機能もあるのですが、今回は省略します。この自動インストール自体は、開発環境の初回起動時に動作しています)
リソース作成(開発フェーズ) †
今度は、DB定義情報からリソース情報を作成します。
カラム、ラベル、コードリソースの登録 †
リソース情報を作成します。作成する対象は、カラム、ラベル、コードリソースです。
画面リソースは、後で画面から手で登録します。ユーザーリソースについては、今回は、システムユーザー(admin)を使用するため、作成しません。
リソースを作成する画面は、「拡張機能」 -> 「リソース連携」です。
この画面で、From,Toの両方のシステムIDに"KK"を入れ、
- テーブルDB⇒ラベルリソース差分追加
- テーブルカラムDB⇒カラム・ラベルリソース差分追加
- テーブルカラムDB(備考)⇒コードリソース差分追加更新
の3つで、それぞれチェックを入れて検索した結果、表示された全ての明細にチェックを入れ、登録します。
これで、リソース情報の登録は完了しました。
(アーカイブファイル(kakeibo.zip)を利用してコンテキストを作成した場合は、リソースが自動登録されています。この場合、上記の検索を行っても、差分情報が表示されません。)
画面リソースの登録 †
管理メニューの画面リソース登録の画面より、画面リソースを登録します。
画面一覧で定義した画面の一覧を元に、画面リソースを登録していきます。
「月度集計検索」及び「収支明細登録」は利用頻度が高いため直リンクに指定しました。
(実際に登録したデータはこちら→
gamenres.txt ※RESULT画面の右側にあるファイル出力ボタンより抜き出したデータです)
画面リソースの追加が終わったら、コンテキストの追加を参考に、kkの追加を行います。
設定後、http://localhost:8824/kk/jsp/index.jspにアクセスし、下のようにメニュー一覧が表示されることを確認します。
(現時点では、まだ画面のJSPソースのフォルダを作成していないため、各画面をクリックしても404 Not Foundが表示されます)
各画面の作成(開発フェーズ) †
やっとここまで来ました。後は、各画面を作成すれば、完成です。
画面フォルダの作成 †
まずは、元となる画面雛形をコピーして、画面リソースで登録した各画面IDに対応する画面ソースフォルダを作成します。
作成対象となる画面は、
- 口座マスタ登録画面 (KK0101)
- 収支分類マスタ登録画面 (KK0102)
- 月度範囲マスタ登録画面 (KK0103)
- 収支明細登録画面 (KK0111)
- 月度集計検索画面 (KK0211) の5画面です。
次に、雛形ソースを選択します。今回は、最後の画面以外は、一般的な一覧検索・一覧登録の画面ですので、 リソース登録画面の中でも一番簡単な、Type1:標準(タグ) (gf/jsp/GF9110)を元にします。
早速、該当のJSPをコピーし、kk/jsp/以下に上記の画面分作成します。
これで、画面開発を行う準備ができました。
各画面の開発 †
各画面の開発ですが、マスタ登録系と、収支明細登録画面については、画面の作りがほとんど同じです。
また、月度集計検索は、登録処理もなくさらにレベルは低くなります。
このため、今回は、代表として、口座マスタ登録(KK0101)で説明を行います。
口座マスタ登録画面(KK0101) †
まず、ソースの構成です。
query.jsp -> 検索条件を記述します。
result.jsp -> 検索条件よりクエリを発行し、結果を画面に表示します。
update.jsp -> 複写、変更、削除が押された場合に、このページに遷移します。
entry.jsp -> update.jspで登録を押した後、このJSPでDBへの登録を行います
処理後、result.jspに自動遷移します。
forward.jsp -> ページ遷移を制御します。
※通常変更する必要はありません。
index.jsp -> QUERY と RESULT フレーム分割を定義しています。
※通常変更する必要はありません。
ということで、上の4つのJSPを画面に合わせて修正します。
- query.jsp
検索条件の入力ボックスを記述するタグは、og:columnです。これを列挙し、検索条件の画面を作成します。<form method="GET" action="forward.jsp" target="RESULT" onClick="timeSet();"> <table summary="layout" > <tr> <og:column name="CDKOUZA" renderer="LABEL" editor="TEXT" /> <og:column name="NMKOUZA" /> <og:column name="MOKUTEKI" /> <og:column name="FGJ" defaultVal="1" /> </tr> </table> <og:queryButton> <table> <tr> <og:select name="ORDER_BY" lbl="ORDER_BY"> <og:option value="SEQNO" lbls="SEQNO" selected="selected" /> </og:select> </tr> </table> </og:queryButton> </form>
下のソースに記述されている、og:selectの部分では、表示順(orderBy句の値)をプルダウンとして定義しています。
※ タグの一覧及び、タグの属性情報の一覧は、「ドキュメント」 -> 「タグリブ定義」「「タグリブ属性定義」の画面より確認することができます。(タグリブマニュアルを参照) - result.jsp
検索条件で入力した値を元に、クエリを生成します。
クエリを生成するためのタグは、og:query、og:where、og:andタグです。<og:query command="{@command}" debug="{@debug}" maxRowCount="{@maxRowCount}"> <jsp:text> select * from KK01 where USERID = '{@USER.ID}' </jsp:text> <og:where startKey="and"> <og:and value = "CDKOUZA = '{@CDKOUZA}'" /> <og:and value = "NMKOUZA like '{@NMKOUZA}%'" /> <og:and value = "MOKUTEKI like '{@MOKUTEKI}%'" /> <og:and value = "FGJ = '{@FGJ}'" /> </og:where> <og:appear startKey = "order by" value = "{@ORDER_BY}" defaultVal = "SEQNO" /> </og:query>query.jspで記述した検索条件で入力された値は、{@カラム名}という形式で取得することができます。
また、og:andタグでwhere条件を記述することで、{@カラム名}の値がnullでない場合(=検索条件が入力された場合)のみ、その条件句が有効になります。(nullの場合は、条件式が削除されます)
USERIDの条件に記載されてる{@USER.ID}では、ログインユーザーを取得することができます。
また、og:appearタグでは、prefix(startKey属性)を指定して、value属性に指定された値から、orderBy句を生成しています。次に、og:submitタグを使用して、編集画面に遷移するためのボタンを生成します。
(現時点では、og:writeCheckタグはオマジナイだと思ってもらって構いません)<og:writeCheck> <og:submit value="update" lbl="COPY" command="COPY" accesskey="C" keys="noWritable" vals="null" /> <og:submit value="update" lbl="MODIFY" command="MODIFY" accesskey="M" keys="noWritable" vals="CDKOUZA" /> <og:submit value="update" lbl="DELETE" command="DELETE" accesskey="D" keys="columnWritable,logicalDelete" vals="null,true" /> <og:submit value="update" lbl="DELETE_PH" command="DELETE" roles="DEL" keys="columnWritable" vals="null" /> <br /> </og:writeCheck>
og:submitタグのvalue属性で、遷移する先のJSPを指定しています。複写、変更、削除、物理削除の全てで、遷移先は同じupdate.jspです。
但し、同じJSPでもcommand値を変更することで、挙動を制御しています。(詳細は、update.jspの項を参照)最後に、発行したクエリの結果を画面に表示します。<og:view viewFormType = "HTMLTable" command = "{@command}" noDisplay = "USERID,UNIQ,FGJ,USRSET,DYSET,USRUPD,DYUPD,PRGUPD" checked = "{@checked}" startNo = "{@startNo}" pageSize = "{@pageSize}" />これで、検索結果が画面に表示されます。 - update.jsp
ここでまず重要なのは、はじめの方に記述されているog:entryタグです。<og:entry command="{@command}" > <og:columnSet command="{@command}" columnId="USERID" action="NULLSET" value="{@USER.ID}" /> <og:columnSet command="COPY" columnId="UNIQ" action="CLEAR" /> <og:columnSet command="COPY" columnId="USRSET" action="SET" value="{@USER.ID}" /> <og:columnSet command="COPY" columnId="DYSET" action="SET" value="{@USER.YMDH}" /> <og:columnSet command="{@command}" columnId="USRUPD" action="SET" value="{@USER.ID}" /> <og:columnSet command="{@command}" columnId="DYUPD" action="SET" value="{@USER.YMDH}" /> <og:columnSet command="{@command}" columnId="PRGUPD" action="SET" value="{@GUI.KEY}" /> <og:columnSet command="DELETE" columnId="FGJ" action="SET" value="9" /> </og:entry>このog:entryタグでは、command変数の値に応じて、DBテーブルモデルの行操作を行っています。COPY -> 選択行の直下にコピー行を編集可能な状態で追加(改廃C=A) MODIFY -> 選択行を編集可能な状態に変更(改廃C=C) DELETE -> 選択行を編集可能な状態に変更(改廃C=D)
次に登録ボタンを生成します。<og:writeCheck> <og:submit value="entry" lbl="ENTRY" accesskey="E" /> <og:submit value="reset" lbl="RESET" accesskey="R" /> <og:input type="reset" name="command" lbl="MSG0011" td="false" /> </og:writeCheck>
後は、操作された後のDBテーブルモデルをog:viewタグで同じように表示します。<og:view viewFormType = "HTMLTable" command = "{@command}" noDisplay = "USERID,UNIQ,FGJ,USRSET,DYSET,USRUPD,DYUPD,PRGUPD" columnWritable= "{@columnWritable}" noWritable = "{@noWritable}" startNo = "{@startNo}" checked = "{@checked}" pageSize = "{@pageSize}" /> - entry.jsp
ここでまず重要なのは、はじめの方に記述されているog:columnCheckタグ、og:entryタグです。<og:columnCheck command="{@command}" /> <og:entry command="{@command}" />og:columnCheckタグでは、各入力項目に対して、カラムリソースの文字種別の定義に従い、データのバリデーションを行っています。
また、og:entryタグでは、入力値(リクエストパラメーター)をDBテーブルモデルに登録しています。次にog:tableUpdateタグ、og:tableUpdateParam?タグを用いて、DBテーブルモデルの内容から、insert、update、delete文を生成し、DBへの登録を行います。<og:tableUpdate command = "{@command}" queryType = "JDBCTableUpdate"> <og:tableUpdateParam sqlType = "{@sqlType}" table = "KK01" where = "UNIQ = [UNIQ]" logicalDelete = "{@logicalDelete}" /> </og:tableUpdate>og:tableUpdateParam?タグでは、sqlType変数(=update.jspに遷移した際のcommand変数の値)に応じて、DML文を作成しています。
og:tableUpdateタグでは、生成されたSQL文を選択された行数文ループし、各行に対して、DBへの登録を行っています。最後に、og:forwardタグを利用して、result.jspに遷移することで登録処理が完了します。<og:forward page="result.jsp" keys="command" vals="RENEW" />
以上で画面作成の説明は終わりです。
最後に †
いかがでしたでしょうか?
フレームワークを用いた開発、という観点では、カスタムタグ(og:)の使用方法さえ覚えれば、開発を行うことができます。
後は、検索を行うためのSQL文と、(今回は省略した)業務ロジックを記述するためのストアドプロシージャ(PL/SQL)の記述方法を覚えればシステム開発を行うことができます。
個々のケースについては、順次説明を追加していきたいと思います。
添付ファイル: