※当サイトの記事には、広告・プロモーションが含まれます。

MyBatisの雛型を作ってくれるMyBatis Generator (MBG)を使ってみる

www.itmedia.co.jp

⇧ amazing...

MyBatis Generator (MBG)とは?

GitHubの公式のドキュメントによりますと、

github.com

This is a code generator for MyBatis.

This library will generate code for use with MyBatis. It will introspect a database table (or many tables) and will generate artifacts that can be used to access the table(s). This lessens the initial nuisance of setting up objects and configuration files to interact with database tables. MBG seeks to make a major impact on the large percentage of database operations that are simple CRUD (Create, Retrieve, Update, Delete).

https://github.com/mybatis/generator

MBG can generate code in multiple styles (or "runtimes"). MBG can generate code for Java based projects, or for Kotlin based projects.

https://github.com/mybatis/generator

⇧ MyBatisのためのコードジェネレーターらしい。

公式のドキュメントによると、

mybatis.org

When running as an Eclipse feature the generator can also merge Java files and save user modifications to the generated Java files. The generator uses the Eclipse Java parser and AST walker to accomplish this. The Eclipse feature also has a few user interface enhancements that make the generator somewhat easier to run. Lastly, the Eclipse feature contributes a full user manual for the generator to the Eclipse help system.

The Eclipse feature can be found on the Eclipse marketplace here: https://marketplace.eclipse.org/content/mybatis-generator

http://mybatis.org/generator/

Eclipseで利用できるらしい。

公式のQuick Startを確認したところ、

mybatis.org

Eclipseを使わなくても通常のjavaコマンドでも実行できる模様。

他にもいろいろ実行方法はあるらしく、

mybatis.org

MyBatis Generator (MBG) can be run in the following ways:

http://mybatis.org/generator/running/running.html

⇧ 上記の方法が用意されてる模様。

MyBatisの雛型を作ってくれるMyBatis Generator (MBG)を使ってみる

「MyBatis Generator (MBG)」を使う場合、事前にデータベースにテーブルなどは作成されている必要があるので、

ts0818.hatenablog.com

⇧ 前回の記事と同じテーブルを使うことします。データベースはPostgreSQLを使っています。

Eclipseで「MyBatis Generator (MBG)」を試してみる。

mybatis.org

⇧ 上記を参考にさせていただきます。

EclipseのマーケットプレースからプラグインEclipseにインストールする必要があるみたい。

Eclipseを起動したら、「ヘルプ(H)」>「Eclipse マーケットプレース(M)...」を選択。

mybatis generatorで検索したら、「MyBatis Generator 1.4.1」というのがヒットしたので、インストールしてみます。

「使用条件の条項に同意します(A)」にチェックし、「完了(F)」ボタンを押下。

「はい、リスクに同意」ボタンを押下。

Eclipseの再起動を促されるので、問題なければ「今すぐ再起動(R)」ボタンを押下。

そしたらば、「パッケージ・エクスプローラー」上で、MyBatisの雛型を作成したいプロジェクトを選択した状態で右クリックし、「新規(W)」>「その他(O)...」を選択。

「MyBatis」>「MyBatis Generator Configuration File」を選択し、「次へ(N)>」ボタンを押下。

特に何も変更せず、「完了(F)」ボタンを押下しました。

そうすると、プロジェクト直下に「generatorConfig.xml」というファイルが作成されます。

初期状態の「generatorConfig.xml」は以下のような感じになってました。

■/mybatis-example/generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
  <context id="context1">
    <jdbcConnection connectionURL="???" driverClass="???" password="???" userId="???" />
    <javaModelGenerator targetPackage="???" targetProject="???" />
    <javaClientGenerator targetPackage="???" targetProject="???" type="XMLMAPPER" />
    <table schema="???" tableName="???">
      <columnOverride column="???" property="???" />
    </table>
  </context>
</generatorConfiguration>    

⇧ これを編集していくということだと思うのだけど、

mybatis.org

mybatis.org

⇧ 公式の説明が分かり辛い...

とりあえず、最低限必要そうな情報を設定してみる。

■/mybatis-example/generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
  <context id="context1" targetRuntime="MyBatis3">
    <jdbcConnection driverClass="org.postgresql.Driver"
           connectionURL="jdbc:postgresql://localhost:5434/test"
           password="postgres"
           userId="postgres" />
    <javaModelGenerator targetPackage="com.example.demo.entity" targetProject="mybatis-example/src/main/java">
      <property name="enableSubPackages" value="true" />
    </javaModelGenerator>
    <sqlMapGenerator targetPackage="com.example.demo.mapper" targetProject="mybatis-example/src/main/resources">
      <property name="enableSubPackages" value="true" />
    </sqlMapGenerator>
    <javaClientGenerator targetPackage="com.example.demo.repository" targetProject="mybatis-example/src/main/java" type="XMLMAPPER">
      <property name="enableSubPackages" value="true" />
    </javaClientGenerator>
    <table schema="" tableName="area">
          <property name="useActualColumnNames" value="true" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
    </table>
    <table schema="" tableName="prefectures">
          <property name="useActualColumnNames" value="true" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
    </table>
    <table schema="" tableName="shikoku_ohenro">
          <property name="useActualColumnNames" value="true" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
    </table>
  </context>
</generatorConfiguration>

⇧ で保存したらば、「generatorConfig.xml」を選択した状態で右クリックし、「実行(R)」>「1 Run MyBatis Generator」を選択。

何か、Entityクラスについては、既にファイルが存在してる場合は、追記されるらしく、idが重複とかのエラーになってしまった。

⇧ あと、〇〇Example.javaってファイルも作成されるのですが、用途については

tech-blog.tsukaby.com

⇧ 上記サイト様が詳しいです。

「MyBatis Generator (MBG)」で雛型を作ると、XMLベースになるっぽいので、アノテーションを元に作ってるプロジェクトとバッティングしてしまうってことですかね。

となると、やはり、MyBatisはXMLで使うのが主流派ってことになるのかな?

MyBatisのXMLの記述の仕方を学習する必要が出てくるってことですね...

と思ったら、

mybatis.org

⇧ typeで選べるみたい。

というわけで、typeをアノテーションXMLの両方が使える、「MIXEDMAPPER」にしてみます。

■/mybatis-example/generatorConfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
  <context id="context1" targetRuntime="MyBatis3">
    <jdbcConnection driverClass="org.postgresql.Driver"
           connectionURL="jdbc:postgresql://localhost:5434/test"
           password="postgres"
           userId="postgres" />
    <javaModelGenerator targetPackage="com.example.demo.entity" targetProject="mybatis-example/src/main/java">
      <property name="enableSubPackages" value="true" />
    </javaModelGenerator>
    <sqlMapGenerator targetPackage="com.example.demo.mapper" targetProject="mybatis-example/src/main/resources">
      <property name="enableSubPackages" value="true" />
    </sqlMapGenerator>
    <javaClientGenerator targetPackage="com.example.demo.repository" targetProject="mybatis-example/src/main/java" type="MIXEDMAPPER">
      <property name="enableSubPackages" value="true" />
    </javaClientGenerator>
    <table schema="" tableName="area">
          <property name="useActualColumnNames" value="true" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
    </table>
    <table schema="" tableName="prefectures">
          <property name="useActualColumnNames" value="true" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
    </table>
    <table schema="" tableName="shikoku_ohenro">
          <property name="useActualColumnNames" value="true" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
    </table>
  </context>
</generatorConfiguration>    

⇧ 上記で再度、MyBatis Generator (MBG)を実行してみると、

package com.example.demo.repository;

import java.util.List;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;

import com.example.demo.entity.ShikokuOhenro;
import com.example.demo.entity.ShikokuOhenroExample;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.ResultMap;
import org.apache.ibatis.annotations.Update;

@Mapper
public interface ShikokuOhenroMapper {

	/**
	 * This method was generated by MyBatis Generator. This method corresponds to the database table shikoku_ohenro
	 * @mbg.generated  Wed Nov 09 12:23:46 JST 2022
	 */
	long countByExample(ShikokuOhenroExample example);

	/**
	 * This method was generated by MyBatis Generator. This method corresponds to the database table shikoku_ohenro
	 * @mbg.generated  Wed Nov 09 12:23:46 JST 2022
	 */
	int deleteByExample(ShikokuOhenroExample example);

	/**
	 * This method was generated by MyBatis Generator. This method corresponds to the database table shikoku_ohenro
	 * @mbg.generated  Wed Nov 09 12:23:46 JST 2022
	 */
	@Delete({ "delete from shikoku_ohenro", "where id = #{id,jdbcType=INTEGER}" })
	int deleteByPrimaryKey(Integer id);

	/**
	 * This method was generated by MyBatis Generator. This method corresponds to the database table shikoku_ohenro
	 * @mbg.generated  Wed Nov 09 12:23:46 JST 2022
	 */
	@Insert({ "insert into shikoku_ohenro (id, name_fudasyo, ", "kana_name_fudasyo, rome_name_fudasyo, ",
			"name_temple, kana_name_temple, ", "rome_name_temple, prefectures_id, ", "created, updated, ",
			"is_deleted)", "values (#{id,jdbcType=INTEGER}, #{name_fudasyo,jdbcType=VARCHAR}, ",
			"#{kana_name_fudasyo,jdbcType=VARCHAR}, #{rome_name_fudasyo,jdbcType=VARCHAR}, ",
			"#{name_temple,jdbcType=VARCHAR}, #{kana_name_temple,jdbcType=VARCHAR}, ",
			"#{rome_name_temple,jdbcType=VARCHAR}, #{prefectures_id,jdbcType=INTEGER}, ",
			"#{created,jdbcType=TIMESTAMP}, #{updated,jdbcType=TIMESTAMP}, ", "#{is_deleted,jdbcType=BIT})" })
	int insert(ShikokuOhenro row);

	/**
	 * This method was generated by MyBatis Generator. This method corresponds to the database table shikoku_ohenro
	 * @mbg.generated  Wed Nov 09 12:23:46 JST 2022
	 */
	int insertSelective(ShikokuOhenro row);

	/**
	 * This method was generated by MyBatis Generator. This method corresponds to the database table shikoku_ohenro
	 * @mbg.generated  Wed Nov 09 12:23:46 JST 2022
	 */
	List<ShikokuOhenro> selectByExample(ShikokuOhenroExample example);

	/**
	 * This method was generated by MyBatis Generator. This method corresponds to the database table shikoku_ohenro
	 * @mbg.generated  Wed Nov 09 12:23:46 JST 2022
	 */
	@Select({ "select", "id, name_fudasyo, kana_name_fudasyo, rome_name_fudasyo, name_temple, kana_name_temple, ",
			"rome_name_temple, prefectures_id, created, updated, is_deleted", "from shikoku_ohenro",
			"where id = #{id,jdbcType=INTEGER}" })
	@ResultMap("com.example.demo.repository.ShikokuOhenroMapper.BaseResultMap")
	ShikokuOhenro selectByPrimaryKey(Integer id);

	/**
	 * This method was generated by MyBatis Generator. This method corresponds to the database table shikoku_ohenro
	 * @mbg.generated  Wed Nov 09 12:23:46 JST 2022
	 */
	int updateByExampleSelective(@Param("row") ShikokuOhenro row, @Param("example") ShikokuOhenroExample example);

	/**
	 * This method was generated by MyBatis Generator. This method corresponds to the database table shikoku_ohenro
	 * @mbg.generated  Wed Nov 09 12:23:46 JST 2022
	 */
	int updateByExample(@Param("row") ShikokuOhenro row, @Param("example") ShikokuOhenroExample example);

	/**
	 * This method was generated by MyBatis Generator. This method corresponds to the database table shikoku_ohenro
	 * @mbg.generated  Wed Nov 09 12:23:46 JST 2022
	 */
	int updateByPrimaryKeySelective(ShikokuOhenro row);

	/**
	 * This method was generated by MyBatis Generator. This method corresponds to the database table shikoku_ohenro
	 * @mbg.generated  Wed Nov 09 12:23:46 JST 2022
	 */
	@Update({ "update shikoku_ohenro", "set name_fudasyo = #{name_fudasyo,jdbcType=VARCHAR},",
			"kana_name_fudasyo = #{kana_name_fudasyo,jdbcType=VARCHAR},",
			"rome_name_fudasyo = #{rome_name_fudasyo,jdbcType=VARCHAR},",
			"name_temple = #{name_temple,jdbcType=VARCHAR},",
			"kana_name_temple = #{kana_name_temple,jdbcType=VARCHAR},",
			"rome_name_temple = #{rome_name_temple,jdbcType=VARCHAR},",
			"prefectures_id = #{prefectures_id,jdbcType=INTEGER},", "created = #{created,jdbcType=TIMESTAMP},",
			"updated = #{updated,jdbcType=TIMESTAMP},", "is_deleted = #{is_deleted,jdbcType=BIT}",
			"where id = #{id,jdbcType=INTEGER}" })
	int updateByPrimaryKey(ShikokuOhenro row);

	@Select("select * from shikoku_ohenro where id = #{id}")
	ShikokuOhenro findById(@Param("id") Long id);
	
	@Select("select * from shikoku_ohenro")
	List<ShikokuOhenro> findAll();

}

アノテーションを利用したSQLも追加されました。

う~む、結局のところ、MyBatisを使う場合、アノテーションXMLのどっちを使っていけば良いのかが分からん...

悲報...

stackoverflow.com

Yes,the documentation for Mybatis cautions that annotations can be much simpler and easier to read for smaller, simpler projects. However, annotations are limited compared to the XML configuration. If your project includes complex objects or a complex database structureconsider using the XML configuration instead of the Java annotations.

https://stackoverflow.com/questions/32631438/mybatis-xml-vs-annotation

⇧ 複雑なオブジェクトや複雑なデータベースを含んだプロジェクトであれば、XMLを利用したほうが良いみたい...

ってことは、大規模なシステムは、XMLを利用してるってことになりそうね...

XMLでのMyBatisの使い方を学習する必要がありそうですね...

他にも実装方法があるらしく、

qiita.com

⇧ 上記サイト様が詳しいです。

2022年11月12日(土)追記:↓ ここから

XMLファイルと、Java側のRepositoryインターフェイスについて、

springhack.com

⇧ パッケージを合わせる必要があるようです。

あとは、XMLアノテーションが混在してるとSpring Batchと組み合わせた時にエラーになってしまうので、「MyBatis Generator (MBG)」を使う場合はXMLだけにした方が良さ気なのでtypeを「XMLMAPPER」にした方が良さそうです。

そして、主キーとかの対応で、

mybatis.org

The <generatedKey> element is used to specify properties for auto generated keys (from identity field or sequences). If you specify this element, MyBatis Generator (MBG) will generate an appropriate <selectKey> element inside the generated <insert> element in the SQL map. This element is an optional child element of the <table> element.

https://mybatis.org/generator/configreference/generatedKey.html

⇧「generatorConfig.xml」に、<generatedKey>を設定した方が良さそうなので、

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
  <context id="context1" targetRuntime="MyBatis3">
    <jdbcConnection driverClass="org.postgresql.Driver"
           connectionURL="jdbc:postgresql://localhost:5434/test"
           password="postgres"
           userId="postgres" />
    <javaModelGenerator targetPackage="com.example.demo.entity" targetProject="mybatis-example/src/main/java">
      <property name="enableSubPackages" value="true" />
    </javaModelGenerator>
    <sqlMapGenerator targetPackage="com.example.demo.repository" targetProject="mybatis-example/src/main/resources">
      <property name="enableSubPackages" value="true" />
    </sqlMapGenerator>
    <javaClientGenerator targetPackage="com.example.demo.repository" targetProject="mybatis-example/src/main/java" type="XMLMAPPER">
      <property name="enableSubPackages" value="true" />
    </javaClientGenerator>
    <table schema="" tableName="area">
          <property name="useActualColumnNames" value="true" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
          <generatedKey column="id" sqlStatement="JDBC" identity="true" />
          <columnOverride column="updated" isGeneratedAlways="True"></columnOverride>
          <columnOverride column="created" isGeneratedAlways="True"></columnOverride>
    </table>
    <table schema="" tableName="prefectures">
          <property name="useActualColumnNames" value="true" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
          <generatedKey column="id" sqlStatement="JDBC" identity="true" />
          <columnOverride column="updated" isGeneratedAlways="True"></columnOverride>
          <columnOverride column="created" isGeneratedAlways="True"></columnOverride>
    </table>
    <table schema="" tableName="shikoku_ohenro">
          <property name="useActualColumnNames" value="true" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
          <generatedKey column="id" sqlStatement="JDBC" identity="true" />
          <columnOverride column="updated" isGeneratedAlways="True"></columnOverride>
          <columnOverride column="created" isGeneratedAlways="True"></columnOverride>
    </table>
        <table schema="" tableName="shikoku_ohenro_user">
          <property name="useActualColumnNames" value="true" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
          <generatedKey column="id" sqlStatement="JDBC" identity="true" />
          <columnOverride column="updated" isGeneratedAlways="True"></columnOverride>
          <columnOverride column="created" isGeneratedAlways="True"></columnOverride>
    </table>
  </context>
</generatorConfiguration>    

⇧ tableの部分の設定を追記しました。

2022年11月12日(土)追記:↑ ここまで

2022年11月18日(金)追記:↓ ここから

Entityクラスなどのフィールドがスネークケースで作成されてしまうので、修正。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN" "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
  <context id="context1" targetRuntime="MyBatis3">
    <jdbcConnection driverClass="org.postgresql.Driver"
           connectionURL="jdbc:postgresql://localhost:5434/test"
           password="postgres"
           userId="postgres" />
    <javaModelGenerator targetPackage="com.example.demo.entity" targetProject="mybatis-example/src/main/java">
      <property name="enableSubPackages" value="true" />
    </javaModelGenerator>
    <sqlMapGenerator targetPackage="com.example.demo.repository" targetProject="mybatis-example/src/main/resources">
      <property name="enableSubPackages" value="true" />
    </sqlMapGenerator>
    <javaClientGenerator targetPackage="com.example.demo.repository" targetProject="mybatis-example/src/main/java" type="XMLMAPPER">
      <property name="enableSubPackages" value="true" />
    </javaClientGenerator>
    <table schema="" tableName="area">
          <property name="useActualColumnNames" value="false" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
          <generatedKey column="id" sqlStatement="JDBC" identity="true" />
          <columnOverride column="updated" isGeneratedAlways="True"></columnOverride>
          <columnOverride column="created" isGeneratedAlways="True"></columnOverride>
    </table>
    <table schema="" tableName="prefectures">
          <property name="useActualColumnNames" value="false" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
          <generatedKey column="id" sqlStatement="JDBC" identity="true" />
          <columnOverride column="updated" isGeneratedAlways="True"></columnOverride>
          <columnOverride column="created" isGeneratedAlways="True"></columnOverride>
    </table>
    <table schema="" tableName="shikoku_ohenro">
          <property name="useActualColumnNames" value="false" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
          <generatedKey column="id" sqlStatement="JDBC" identity="true" />
          <columnOverride column="updated" isGeneratedAlways="True"></columnOverride>
          <columnOverride column="created" isGeneratedAlways="True"></columnOverride>
    </table>
        <table schema="" tableName="shikoku_ohenro_user">
          <property name="useActualColumnNames" value="false" />
          <property name="mapUnderscoreToCamelCase" value="true"/>
          <generatedKey column="id" sqlStatement="JDBC" identity="true" />
          <columnOverride column="updated" isGeneratedAlways="True"></columnOverride>
          <columnOverride column="created" isGeneratedAlways="True"></columnOverride>
    </table>
  </context>
</generatorConfiguration>    

2022年11月18日(金)追記:↑ ここまで

毎度モヤモヤ感が半端ない...

今回はこのへんで。