ハンズオンセクション 6

概要

さて、ハンズオンの続きです。

"デバッグログ設定と別名(和名)の利用" を学んでいきましょう。

事前準備

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

デバッグログ設定 (Lasta Di なら)

DIコンテナが Lasta Di であれば、logback になっています。

既に何度もデバッグログにはお世話になっているかと思います。 Eclipse (or IntelliJ) のコンソールにはDBFluteの検索処理のログが出力されていたかと思います。 これは、既に src/main/resources 配下に logback.xml が(最初から)配置されているからです。ここでは簡単ではありますが、この設定ファイルを修正すると出力されるログが変更されることを学びましょう。

試しに、logback.xml の org.dbflute の logger タグをコメントアウトして、今まで作った任意のテストを実行し、コンソールのログを確認してみてください。変化があるはずです。 変化を確認したら、元に戻してもう一度テストを実行して確認しましょう。(元に戻さないとログが出なくなっちゃいますよぅ)

デバッグログ設定 (Seasarのままなら)

DIコンテナが Seasar のままであれば、logj4 になっています。

既に何度もデバッグログにはお世話になっているかと思います。 Eclipse (or IntelliJ) のコンソールにはDBFluteの検索処理のログが出力されていたかと思います。 これは、既に src/test/resources 配下に log4j.properties (もしくは、src/main/resources に logback.xml) が(最初から)配置されているからです。ここでは簡単ではありますが、この設定ファイルを修正すると出力されるログが変更されることを学びましょう。

試しに、log4j.properties の log4j.logger.org.seasar を "#" でコメントアウトして、今まで作った任意のテストを実行し、コンソールのログを確認してみてください。変化があるはずです。 変化を確認したら、元に戻してもう一度テストを実行して確認しましょう。

また、log4j.appender.console.layout.ConversionPattern を "%d [%t]-%-5p - %m%n" に変更してみてください。変化を確認したら、元に戻してもう一度テストを実行して確認しましょう。

別名(和名)の利用 (+ Logic作成)

DBコメントの確認

replace-schema-10-basic.sql をご覧ください。 たくさんのDBコメントが定義されています。そして、DBコメントには、そのテーブルやカラムの別名(和名)と説明が "別名 : 説明" という形式で記載されています。まず、SchemaHTML を開いて、DBコメントがその形式であることを確認してください。(全てのコメントが必ずこの形式とは限りません)

ロジックを作りながら確認

それでは唐突ですが、JavaDoc上にDBコメントがあるかどうかを確認するために実装してみましょう。 以下のロジックを作成してテストしてみてください。実装しながら、それぞれのカラムに対応するメソッドの JavaDoc コメントを確認してみてください。特に別名は表示されていないはずです。

ロジックのメソッド
List<Member> selectSuffixMemberList(String suffix)
  • 指定された suffix で会員名称を後方一致検索
  • 会員名称の昇順で並べる
  • suffixが無効な値なら例外: IllegalArgumentException
  • 会員名称、生年月日、正式会員日時をログに出す (Slf4j or CommonsLogging)
  • そのログのログレベル、INFO/DEBUGどちらがいいか考えて実装してみましょう (この先ずっと同じ)
  • このメソッドは、他の人が呼び出すことを想定して public にしましょう (この先ずっと同じ)
対応テストメソッド
test_selectSuffixMemberList_指定したsuffixで検索されること()
  • suffix は "vic" で
  • テストメソッド名通りのアサート
  • テストが成り立っていることも(できる範囲で)アサート (今後ずっとそう)
test_selectSuffixMemberList_suffixが無効な値なら例外が発生すること()
  • 無効な値とは、nullと空文字とトリムして空文字になる値

ロジックの作り方はこのように

ちなみに、今回からエクササイズをより実践に近いもので行います。

  1. ロジッククラスにメソッドを定義して実装 (BehaviorはDIを利用)
  2. (Eclipseであれば) ctrl + 9 で対応するテストクラスを自動生成 (src/test/java に)
  3. (IntellJであれば) ...わからないですが、テストクラスのひながた自動生成できるはずです
  4. テストメソッドを実装してロジックを検証

ロジッククラスでの Behavior の宣言は、以下のようにします。(講師によるDIのお話あり)

e.g. ロジッククラスでの Behavior の宣言 @Java
/**
 * @author jflute
 */
public class HandsOn06Logic {

    @Resource
    private MemberBhv memberBhv;

    ...
}

テストクラスでのロジックの利用方法は、以下のようにします。(講師によるUTFluteのお話あり)

e.g. テストクラスでロジッククラスを生成して利用 @Java
public void test_...() {
    // ## Arrange ##
    HandsOn06Logic logic = new HandsOn06Logic();
    inject(logic);
    
    // ## Act ##
    ... = logic.select...();
    ...
}

DBFluteプロパティの設定

それでは、ドキュメントに関するDBFluteプロパティ、DBFluteクライアントの dfprop/documentMap.dfprop を開いて、以下のプロパティを設定してみましょう。

aliasDelimiterInDbComment
DBコメント内の別名と説明の区切り(デリミタ)を表す文字
設定する値 => : (コロン)
isDbCommentOnAliasBasis
DBコメントの基本が別名か否か (デリミタがない場合にそれは別名なのかどうか)
設定する値 => true

dfpropのひな形コメントを使おう

よく使われるプロパティは、dfpropファイルの中にすでにコメント付きのひな形があります。 それをそのまま活用しましょう。

e.g. コメント付きのDBFluteプロパティ(aliasDelimiterInDbComment)のひな形 @documentMap.dfprop
    # /- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    # o aliasDelimiterInDbComment: (NotRequired - Default '')
    #  If the alias exists in its DB comment like as follows:
    #    member name : The name of member's full name
    #  you can use the alias in DBFlute world, java-doc, SchemaHTML...
    #  DB comment which does not have the delimiter is not treated
    #  as alias, treated as description (real comment).
    #  But you can change it by 'isDbCommentOnAliasBasis'.
    #
    #; aliasDelimiterInDbComment = : // ここのコメントを外して利用しましょう
    # - - - - - - - - - -/

再自動生成して確認

DBFluteプロパティの設定が終わったら、Docタスク、そして、Generateタスクを実行してみてください。 SchemaHTML、および、それぞれのカラムに対応するメソッドの JavaDoc コメントに変化があるはずです。

メソッド補完時のJavaDoc表示

IntelliJのみなさん、デフォルトではメソッド補完時に JavaDoc は表示されないので、 補完中に control+J を押してみてください。これをぜひ習慣化しましょう。

Eclipseの場合は、デフォルトでメソッド補完時に JavaDoc がぴょいぴょいでますので、無視せずに着目しましょう。有益な情報が入っているかもしれませんよ。

getであんまり検索したくない

ハンズオンでは、Logicの検索メソッドの名前は、select...() になっています。データを取得するからget?ではありません。 検索している、探している、ということを意識したいのです。

こういった考えでやっていますので、ぜひいちどお読みくださいませ。

ちょっと大文字にしてみましょうか

ハンズオンのMySQLでは、SQL上で大文字小文字を区別しないで済むような設定がされています。

内部的には、テーブル名を全て小文字で管理することによって実現されています。 よって、DBFluteが取得するメタデータなどが小文字になっています(SchemaHTMLやCBで実行されたSQLなど)。 これを、大文字にするという地味な機能が用意されています。以下のプロパティ(littleAdjustmentMap.dfprop)を設定して再自動生成して確認してみてください。

e.g. DBFlute管理上ではテーブル名を大文字に @littleAdjustmentMap.dfprop
; isTableDispNameUpperCase = true
e.g. DBFluteで発行するSQLのテーブル名やカラム名を大文字に @littleAdjustmentMap.dfprop
; isTableSqlNameUpperCase = true
; isColumnSqlNameUpperCase = true

そもそもテーブル名やカラム名を大文字とするか小文字とするかは、文化や組織によって異なるものです。 どちらが良いという話ではなく、ERDなどのドキュメントと合わせるための地味機能と捉えてください。 (とはいえ、小文字にするプロパティは用意されてないのですが...)

ハンズオンでは、これらプロパティを true に設定して、再自動生成してそれぞれ大文字になっていることを確認してみましょう。

空文字をDBに入れたくない

DB上の空文字は、地味にトラブルを引き起こす可能性があります。

次のセクションから、登録や更新処理を行います。 この時点で、DBに空文字が入らないように施策を打っておきます。 以下のプロパティ (littleAdjustmentMap.dfprop) を設定して再自動生成しておきましょう。

e.g. Entityにセットされた空文字をnullに変換 @littleAdjustmentMap.dfprop
; isEntityConvertEmptyStringToNull = true

特に動作確認のためのエクササイズは用意していませんが、自動生成されたクラスの差分を見て、何が変わったのかだけ確認しておきましょう。 (非常に単純な実装になっています)

DBコメントを充実させましょう!

デコメントを知ろう

まず、こちらのページをじっくりお読みください。

もし、DBFluteのバージョンが古ければ(1.1.6より前だったら)、いますぐ最新にしてみましょう。

デコメントしてみよう

それでは、"ハンズオンのDBも、こんなコメント書いてあったら良かったのに..." を想像して、Intro経由で幾つかのテーブルやカラムに対してデコメントしてみましょう。 同時にブラウザを二つ (タブを二つでもOKかも) 起動して、同じカラムのコメントを修正してコンフリクトも発生させてみてください。

想定通り、pieceファイルが作成されていることを確認しましょう。 (もし、git環境があればコミットしてみましょう。実運用では、それぞれのトピックブランチでのコミットを想定しています)

また、この時点では、ブラウザで直接 SchemaHTML を開いたときは、今回修正・追加したデコメントはまだ反映されていません。 それも確認しておきましょう。

Docを叩いてピックアップ

今度は、Docタスクを叩いてみましょう。

想定通り、pieceファイルは削除され、pickupファイルが作成されていることを確認しましょう。 (もし、git環境があればコミットしてみましょう。実運用では、DB変更専用のブランチでのコミットを想定しています)

そして、ブラウザで直接 SchemaHTML を開いて、反映されていることを確認しましょう。

コンフリクトを直すデコメントを

最後に、コンフリクトを直すデコメントをしておきましょう。 (もし、git環境があれば、これもコミット)

どんなDBコメントを書いたらいいの?

ぜひブログを参考に。

このように、SchemaHTML経由 (Intro経由) で、DBコメントを "みんな" で追加できますので、実務でもどんどん使っていきましょう。

次のセクション

設定系のエクササイズも飛ばさず学んでみたでしょうか?

さて、次のセクションへ