つかびーの技術日記

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

MyBatisでDateではなくCalendarを利用する方法

   

MyBatisはJava言語用のORマッパーライブラリです。使い方は以下のようなサイトを参照すると良いと思います。(この投稿の下の方のサンプルコードでも一応分かるかと思います。)

MyBatisでは日付型はDateのみ

MyBatisでDB上のテーブルを操作するとき、テーブルの列が日付型である場合、JavaではDate型を利用します。

Date型は@Deprecatedによって非推奨にされているメソッドが多く、利用を避けたいという人は少なくないと思います。自分としてはCalendarで統一したい所です。過去に関わったプロジェクトでは基準書でDateの利用を禁止している、ということもありました。

MyBatisのAPIを利用する時、Dateを廃止して、Calendarを利用しようとしても残念ながらMyBatisはCalendarを受け付けてくれません。

MyBatisでCalendarを利用してみる(エラー)

例えばMySQLでDATETIME列を持つテーブルを作成し、以下のようなコードで操作を試みます。DateTableクラスの内部にCalendarを持っており、これをDBに挿入したりDBから取り出そうとします。

Main.java

DateTable.java

DateTableMapper.java

DateTableMapper.xml

database.properties

上記のコードを実行すると、以下のエラーが発生します。

色々メッセージはありますが、Causeの最も右を参照すると「No typehandler found」と出ています。これは「Calendarのインスタンスをマッピングしようとしたけど、Calendar型に対応したTypeHandlerが無いため、どうマッピングしていいか分からないよ」と言っています。

MyBatisはXMLに定義したとおり、SQLを発行しますが、ここで日付の部分はプレースホルダ―になっています。MyBatisはここに値を埋め込むわけですが、未知の型Calendarからどうやって値を取得して埋め込むべきか分かりません。これを指示するためにTypeHandlerが必要なのです。
(SELECTのときも同様で、DBから取得した値でどのようにCalendarインスタンスを生成すればよいかMyBatisは分かりません)

MyBatisでCalendarを利用してみる(TypeHandlerを利用した解決方法)

どうやってCalendarを利用できるようにするかですが、ここではTypeHandlerを利用します。CalendarTypeHandlerを作成し、mybatis-config.xmlにこれを読み込む設定を行います。

CalendarTypeHandler.java

mybatis-config.xml
(</settings>の後に以下を追記します。)

この状態で実行すると正常に動作します。

動作確認はしていますが、国際化対応する必要があるプログラムの場合、上記のCalendarTypeHandlerのCalendarを操作する部分はよく考えた方が良いかもしれません。(今回は考えないで作ったので注意してください)

このように独自のTypeHandlerを利用すれば大抵の型は何とかなります。MyBatis Generatorを利用している場合はもう少し工夫が必要なのですが、Mapper XMLを自分で作成する場合は今回の手法で問題ないかと思います。次回はMyBatis Generatorで出力するクラスをCalendarにする方法を考えます。

 - Java