つかびーの技術日記

(情報)工学修士, 元SIer SE, 現Web系 SEの技術blogです。Scala, Java, JS, TS, Python, Ruby, AWS, GCPあたりが好きです。

MybatisGeneratorとLombokを両立させる

      2013/10/13

MyBatisはJavaのORマッパーです。これを使えばDB接続が楽になります。

MyBatisを利用する時は大きく以下の3つを用意します。

  1. Entityクラス(JavaBean)
  2. Mapperクラス(DAO)
  3. (場合によって)SQLを記述したXML

これらを手で用意するとなると非常に手間がかかるので、MyBatis Generatorというものを利用します。これを使えば接続先のDBとテーブルさえ教えてあげれば、上記3つを自動生成してくれるので煩雑な作業がなくなります。

生成されるEntityクラスはprivateなメンバ変数とgetter/setterを持ちます。ここでこのEntityクラスにLombokを利用することを考えます。getter/setterは既にあるんだから、Lombokは不要とも思いますが、Lombokのアノテーション方式の方がコード量が小さくなり見やすいと思います。他にもToString自動生成とかできますし。

MyBatis GeneratorとLombokの両立

ではどうするかというと、一番単純なのはgetter/setterを全て排除し、@Dataアノテーションを付けることですが、これを手作業でやるのは馬鹿らしい・・・!

そこで、MyBatis GeneratorのPluginを利用できないかと考え、やってみたところ概ね成功したので記載します。

package org.mybatis.generator.plugins;

import java.util.List;
import java.util.Properties;

import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.api.dom.java.FullyQualifiedJavaType;
import org.mybatis.generator.api.dom.java.TopLevelClass;

public class LombokPlugin extends PluginAdapter {
  private FullyQualifiedJavaType lombokData;

  public LombokPlugin() {
    super();
    lombokData = new FullyQualifiedJavaType("lombok.Data");
  }

  public boolean validate(List warnings) {
    // this plugin is always valid
    return true;
  }

  @Override
  public void setProperties(Properties properties) {
    super.setProperties(properties);
  }

  @Override
  public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    makeAnnotation(topLevelClass);
    return true;
  }

  @Override
  public boolean modelPrimaryKeyClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    makeAnnotation(topLevelClass);
    return true;
  }

  @Override
  public boolean modelRecordWithBLOBsClassGenerated(TopLevelClass topLevelClass, IntrospectedTable introspectedTable) {
    makeAnnotation(topLevelClass);
    return true;
  }

  protected void makeAnnotation(TopLevelClass topLevelClass) {
    topLevelClass.addImportedType(lombokData);
    topLevelClass.addAnnotation("@Data");

    // 全てのGetter/Setterを削除する
    topLevelClass.getMethods().clear();
  }
}

大体こんな感じ。コメントが無いので微妙だけど、ようはmakeAnnotationでimport文、アノテーションを追加し、getter/setterメソッドを全て削除する、という方式です。これで上手く行きます。@ToStringとかも@Dataと同じように追加してやれば良いです。

注意

ただ1つだけ問題があって、通常MyBatisGeneratorは何度実行しても上手いこと再生成してくれるのですが、上記のプラグインを利用すると再生成されたEntitiyクラスとMapperクラスは構文やアノテーションが変な事になってしまいます。そのため、再生成するたびにEntitiyとMapperは予め全て削除しておかなければならないです・・・。

きっと上記のクラスの他のメソッドなどで何とかしてやらないといけないんだろうけど、ちゃんとPluginの仕様読んでないので分からない・・・。getter/setter消す所もイレギュラーだし、それが原因かな・・・?

実は公式PluginだけでOK

さて、ここまで説明しましたが、実は単にtoStringやequalsをMyBatisGeneratorで生成させたい場合は公式が用意したPluginを利用する方法もあります。org.mybatis.generator.pluginsパッケージを見るか検索するかすると、ToStringPluginやEqualsHashCodePluginが出てきます。使ったことは無いけど、多分これで目的は果たせると思います。

そんな訳で、どうしてもLombok使いたい!って人だけの情報だよ・・・というオチです。

 - Java ,