この話題の前提
- Doma2を使います。
- Doma-GenでEntityを自動生成します。
- UTCとは、エポック秒とします。
- DBのTIMESTAMP型は、UTC(エポック秒)を保管できるものとします。
参考にさせて頂いたサイト
DBのTIMESTAMP型(日付と時刻)を、エンティティクラスでは、どの型で扱うか?
DBのテーブルに、TIMESTAMP型(日付と時刻)があるとき、どの型で扱うべきか迷いました。
ご意見をお願いいたします。
Doma2でサポートしている日付/時刻型
Doma2では、日付/時刻型として、次のリンク先の型をサポートしています。
http://doma.readthedocs.io/ja/stable/basic/#id4
その中で、日付+時刻を扱う場合は、次のいずれかの型になります。
- java.time.LocalDateTime
- java.sql.Timestamp
- java.util.Date
Doma-Genで生成される型
Doma1時代のDoma-Genでは、TIMESTAMP型(日付と時刻)に対応する型は、java.sql.Timestampでした。
http://doma.seasar.org/extension/doma_gen_gen_task.html#EntityConfig
しかし、Doma2のDoma-Genでは、java.time.LocalDateTimeになっています。
http://doma-gen.readthedocs.io/ja/stable/gen/#entityconfig
java.time.LocalDateTimeの問題だと思う点
次のサイトに詳細がありますが、java.time.LocalDateTimeは、日時をUTCで保持するのではなく、タイムゾーン情報を一切含まない日付時刻
で保持します。
https://qiita.com/dmikurube/items/15899ec9de643e91497c#javatimelocaldatetime
DBのTIMESTAMP型(日付と時刻)では、日時をUTCで保持するので、java.time.LocalDateTimeで扱ってしまうと、タイムゾーン情報が欠落してしまいます。
ちなみに、PostgreSQLでは、内部的にUTCで保管されています。
https://www.postgresql.jp/document/9.6/html/datatype-datetime.html
java.sql.Timestampを使うのがよい?
java.sql.Timestampは、UTCを保持できるため、タイムゾーンを指定すれば、そのタイムゾーンでの日時が決まります。
つまり、システム内部で日時をUTCで取り回していれば、出力の際には、タイムゾーンを指定して、そのタイムゾーンの日時表現に変換できます。
そういった意味で、java.sql.Timestampを使うのがいいのかなと思います。
対して、java.time.LocalDateTimeの場合は、タイムゾーン情報を一切含まない日付時刻
が、どのタイムゾーンの日時表現かを意識して取り扱う必要があります。
例えば、DBも、システムも、日本のタイムゾーンのみのように、1つのタイムゾーンに限定できるのであれば、事が足りるのかもしれません。
Doma-Genで、TIMESTAMP型(日付と時刻)に対応する型を、java.sql.Timestampにする方法
カスタムのGenDialectクラスを用意する。
使用するDBのGenDialectクラス(この例では、PostgreSQLのGenDialectクラス)を継承して、カスタム用のクラスを用意します。
/**
* PostgreSQL用の方言をカスタマイズするクラス
*/
public class CustomPostgresGenDialect extends PostgresGenDialect {
public CustomPostgresGenDialect() {
// タイムゾーン付きのtimestampは、java.sql.Timestampにマッピングする。
classNameMap.put("timestamptz", Timestamp.class.getName());
}
}
Doma-Genのトップレベルパラメーターに指定する。
トップレベルのgenDialectClassName
に、上記のクラスを指定して、Doma-Genを実行します。(タスク実行時のクラスパスに、指定したクラスを含める必要があります。)
http://doma-gen.readthedocs.io/ja/stable/gen/#id2