ハンズオンセクション 11

概要

さて、最終試練です。

"子テーブルへのアプローチ (なんとかReferrer)" を学んでいきましょう。

事前準備

src/main/java 配下に org.docksidestage.handson.logic.HandsOn11Logic クラスを作成してください。この時点では空っぽで構いません。 また、ERDを開いておくと良いでしょう。

【事務連絡】org.dbflute.handson から、org.docksidestage.handson に変わりました。 org.dbfluteで開始した人は、そのまま org.dbflute で続けてOKです。もし、移行するなら log4j.properties と basicInfoMap.dfprop の該当箇所を修正してください。

子テーブルの取得

今までは、基点テーブルと一緒に、親テーブル(many-to-one)、さらにone-to-oneテーブルを取得してきました。 今度は、基点テーブル一つのレコードに対して複数になり得る子テーブルのレコードも取得していきます。

ロジックのメソッド
List<Member> selectPurchaseMemberList(String memberName)
  • 指定された memberName を含んでいる会員名称の会員を検索する
  • その会員に紐づく支払済み購入のデータも取得する
対応テストメソッド
test_selectPurchaseMemberList_会員と購入が検索されていること()
  • 会員名称が "vi" を含んでいる会員を検索
  • 支払済み購入が取得できていることをアサート

子テーブルの条件で絞り込み

今までは、基点テーブルに加えて、親テーブル(many-to-one)、さらにone-to-oneテーブルのカラムの条件で絞り込みをしてきました。 今度は、基点テーブル一つのレコードに対して複数になり得る子テーブルのカラムで絞り込み条件を定義していきます。

ロジックのメソッド
List<Member> selectUnpaidMemberList(String memberName)
  • 未払い購入のある会員を検索する
  • 指定された memberName で含んでいる会員名称の会員を検索する
対応テストメソッド
test_selectUnpaidMemberList_未払い購入がある会員が検索されていること()
  • 会員名称が "vi" を含んでいる会員を検索
  • 検索された会員が未払い購入を持っていることをアサート

子テーブルの導出カラムを取得

今度は、基点テーブル一つのレコードに対して複数になり得る子テーブルのカラムの集計(最大値や平均値など)を導出していきます。

ロジックのメソッド
List<Member> selectLoggedInMemberList(String memberName)
  • 会員と最終ログイン日時を(一緒に)検索する
  • 指定された memberName で含んでいる会員名称の会員を検索する
対応テストメソッド
test_selectLoggedInMemberList_会員と最終ログイン日時が検索されていること()
  • 会員名称が "vi" を含んでいる会員を検索
  • 会員の最終ログイン日時が本当に最終ログイン日時であることをアサート

子テーブルからみまくりの検索

それでは子テーブルからみまくりの検索のエクササイズです。

もし、該当するデータがない場合は、テストケースの中で一時的にデータを更新して、 テストケースが成り立つようにしてみてください。今後も複雑なケースのエクササイズが想定されますので、 ケースがなければ一時的な「ちょこっと更新」で仮想データを作成するようにしてください。

オンパレードの第一歩

さあ、まずは第一歩

ロジックのメソッド
List<Member> selectOnParadeFirstStepMember(boolean completeOnly)
  • 会員ステータス、会員サービス、サービスランク、購入、購入支払、会員ステータス経由の会員ログインも取得
  • (基点テーブルごとの)モバイルからのログイン回数も導出して取得する
  • 指定された判定次第で支払済み購入しか存在しない会員だけを対象にできるように
  • 購入は商品の定価の高い順、購入価格の高い順で並べる
  • 会員ごとの方のログイン回数と購入一覧と購入支払一覧をデバッグログに綺麗に出力する
  • 購入支払は、最も推奨されている方法のみ検索
対応テストメソッド
test_selectOnParadeFirstStepMember_未払い購入の存在しない会員()
  • 未払い購入の存在しない会員だけを検索
  • 未払い購入が存在しないことをアサート
  • 会員ステータス経由の会員ログインが取得できていることをアサート
  • 購入支払が最も推奨されている方法のみ検索されていることをアサート
  • その他、ロジックの中で出力したログを見て期待通りであることを確認
  • 検索された全会員の購入支払金額の合計をstream()で求めてログに出す! (streamチャレンジ)

オンパレードはつづく

つづいていきますよ。

ロジックのメソッド
List<Member> selectOnParadeSecondStepMember()
  • 会員ステータス、購入と商品と購入商品種類数(*1)を一緒に検索
  • 商品ステータスが "生産中止" の商品を買ったことのある会員...もしくは(続く)
  • (続き)手渡しだけでも払い過ぎてるのに未払いになっている購入を持ってる会員にフォローされている会員
  • 購入は商品ステータスの表示順の昇順、購入日時の降順で並べる
  • 会員ごとの購入一覧と商品名称、購入商品種類数をデバッグログに綺麗に出力する
*1: 購入商品種類数は、例えば、A, B, C という商品を買ったことがあるなら 3 (種類)
対応テストメソッド
test_selectOnParadeSecondStepMember_購入のみならず商品も検索()
  • 商品も取得できることをアサート
  • 購入商品種類数が妥当であることをアサート
  • 生産中止の商品を買ったことのある会員が(一人でも)検索されていることをアサート
  • どんな手段でもいいので、手渡しだけでも...(略)ている会員が(一人でも)検索されていることを目視確認

すごいオンパレード

これはすごい。

ロジックのメソッド
List<Member> selectOnParadeXStepMember(int leastLoginCount)
  • 正式会員のときにログインした最終ログイン日時とログイン回数を導出して会員を検索
  • さらに、支払済み購入の最大購入価格を導出して取得
  • もっとさらに、購入と商品と商品ステータスと商品カテゴリと親商品カテゴリ(*1)も取得
  • もっともっとさらに、会員ログイン情報も取得
  • 正式会員のときにログインした最終ログイン日時の降順、会員IDの昇順で並べる
  • ログイン回数が指定された回数以上で絞り込み
  • 仮会員のときにログインをしたことのある会員を検索
  • 自分だけが購入している商品を買ったことのある会員を検索
  • 購入は商品カテゴリ(*1)の親カテゴリ名称の昇順、子カテゴリ名称の昇順、購入日時の降順
  • 会員ログイン情報はログイン日時の降順
*1: 商品カテゴリは、二階層になっていることが前提として
対応テストメソッド
test_selectOnParadeXStepMember_オンパレードであること()
  • ログイン回数が 2 回より多い会員を検索し、結果がその通りであることをアサート
  • 最終ログイン日時の降順と会員IDの昇順で並んでいることをアサート
  • 支払済み購入の最大購入価格が妥当であることをアサート
  • 仮会員のときにログインをしたことのある会員であることをアサート
  • 自分だけが購入している商品を買ったことのある会員であることをアサート

シンプルな応用編

シンプルに応用してみましょう。

ロジックのメソッド
List<ServiceRank> selectServiceRankSummary()
  • サービスランクごとの会員数、合計購入価格、平均最大購入価格(*1)、ログイン数を検索
  • 紐付く会員とその会員に紐付く購入と会員ログインも取得する
  • 会員数の多い順に並べる
*1: 会員ごとの最大購入価格のサービスランクごとの平均 (nullにならないようにすること)
対応テストメソッド
test_selectServiceRankSummary_集計されていること()
  • 会員数が妥当であることをアサート
  • 検索した内容をログに綺麗に出して目視で確認すること

さらにシンプルな応用編

さらにシンプルに!

ロジックのメソッド
Integer selectMaxAvgPurchasePrice()
  • それぞれの会員の平均購入価格の会員全体での最大値を検索
対応テストメソッド
test_selectMaxAvgPurchasePrice_平均の最大の会員()
  • 平均の最大価格に該当する会員が存在することをアサート

Ending

Enjoy your DBFlute life! See you.