つかびーの技術日記

情報系修士卒のWeb系技術日記です。現在のフォーカス分野はアドテクです。

MyBatis GeneratorのExampleクラスなど解説

   

MyBatis Generatorを使うと、MyBatisを利用する時に必要な煩雑な作業(SQL記述、XML作成、Entityクラス作成など)を自動化してくれます。

このMyBatis Generatorですが、デフォルトで****Exampleというクラスまで作成されるようになっています。少し使ってみると、「ああ、and条件とかを表すためのクラスなのね」と分かるのですが、情報不足で詳しいことが分かりません。

勿論公式にExample Class Usage Notesという情報はありますが、英語だし・・・というわけで使い方を調査・解説します。

テーブル

まずは検証用に適当なテーブルとビューを作成します。

Generater起動

上記のテーブルに対してGeneratorを実行します。ここでできたMapperクラスとそのXMLを検証して行きます。

検証対象

Mapperを見るといくつかメソッドが用意されています。例えばProducerMapperは以下のようになっています。 これらを見ていくことにします。

  1. int countByExample(ProducerExample example)
  2. int deleteByExample(ProducerExample example)
  3. int deleteByPrimaryKey(Long producerId)
  4. int insert(Producer record)
  5. int insertSelective(Producer record)
  6. List selectByExample(ProducerExample example)
  7. Producer selectByPrimaryKey(Long producerId)
  8. int updateByExampleSelective(@Param(“record”) Producer record, @Param(“example”) ProducerExample example)
  9. int updateByExample(@Param(“record”) Producer record, @Param(“example”) ProducerExample example)
  10. int updateByPrimaryKeySelective(Producer record)
  11. int updateByPrimaryKey(Producer record)

ByPrimaryKey系

これは単純です。例えばdeleteByPrimaryKeyのXMLは以下のようになっています。

単純に主キーを仮引数にもつ削除メソッドです。

ByExample系

問題のExampleです。まずは公式の情報を翻訳してみることにします。英語苦手ですが・・・。

The example class specifies how to build a dynamic where clause.

Exampleクラスは動的WHERE句を構築する方法を規定します。

The example classes contain an inner static class called Criteria that holds a list of conditions that will be anded together in the where clause.

Exampleクラスは、WHERE句にANDで結合される条件のリストを持つCriteriaという静的内部クラスを含みます。

なるほど、まあようするにExampleクラスはWHEREなわけです。では実際に使っていきます。説明の都合上、ここではDBのVIEWが元となっているProductDetailMapperのメソッドを検証します。あらかじめVIEW(DB)に以下のデータが投入されていることとします。

PRODUCT_ID PRODUCT_NAME PRODUCER_ID PRODUCER_NAME
100 PRODUCT_1 0 PRODUCER_A
101 PRODUCT_2 0 PRODUCER_A
102 PRODUCT_3 0 PRODUCER_A
103 PRODUCT_4 0 PRODUCER_A
104 PRODUCT_5 2 PRODUCER_C
105 PRODUCT_6 2 PRODUCER_C
106 PRODUCT_7 2 PRODUCER_C
107 PRODUCT_8 2 PRODUCER_C
108 PRODUCT_9 3 PRODUCER_D
109 PRODUCT_10 3 PRODUCER_D
110 PRODUCT_11 4 PRODUCER_E

この状態で以下のコードを実行します。

実行結果は以下です。

なるほど、まずはPrimaryKeyでない条件で検索できました。AND条件1つです。

では次に検索条件をもう一つ追加してみます。

1レコードに絞れました。AND条件が2つです。

ORもできるようなので、試してみることにします。PRODUCER_AのPRODUCT_1とPRODUCER_CのPRODUCT_5の2レコードを抽出します。orメソッドを利用します。

抽出できました。

上記のコードではor()メソッドを利用しました。ここでもし、間違えてcreateCriteriaを実行した場合は?上記の引用通り、Exampleクラス内ではCriteriaをリストで持っていますが、生成されたCriteriaはこのリストに追加されないため、コードは意図通り動きません。

上記のコードではcreateCriteriaを利用しましたが、実は1つ目のcreateCriteriaはorでも正しく動作します。orでも内部ではCriteriaを生成します。常にorで良いかもしれません。

Selective系

insertとupdateにSelectiveがあります。これは一体何なんでしょうか。XMLを見ると分かりました。nullの要素のことを言っているようです。Selectiveではパラメータのクラス内のメンバ変数がnullである場合は、それについては関与しない、というもののようです。

例えばupdateしとうとしたときにメンバ変数がnullだとして、果たしてそれはDB上でNULLにしたいのか、それともDB上の値には関与してほしくないのか・・・このSelectiveはDB上の値はNULLにしないということでしょう。逆にSelectiveでない方のメソッドではメンバ変数がnullの場合はDB上の値もNULLにするということでしょう。

実際にコードを実行して確かめてみます。

ここで分かりやすさのために、PRODUCERテーブルのPRODUCER_NAME列のデフォルト値’NONAME’を設けておきます。

まずは以下のコードを実行します。Selectiveでないバージョン。

PRODUCER_ID PRODUCER_NAME
0 PRODUCER_A
1 PRODUCER_B
2 PRODUCER_C
3 PRODUCER_D
4 PRODUCER_E
900 ​(NULL)​

PRODUCER_NAME列がNULLということはDEFAULTは発動していません。これは意図通りと言えるかと思います。SelectiveしないinsertでNULLの値を意図的に入れたわけですから。

では次はSelectiveバージョンを試してみます。

PRODUCER_ID PRODUCER_NAME
0 PRODUCER_A
1 PRODUCER_B
2 PRODUCER_C
3 PRODUCER_D
4 PRODUCER_E
900 ​(NULL)​
901 NONAME

こちらはDEFAULTが発動してNONAMEになりました。

以上で調査と解説は終了です。

 - Java