Spring Data JPA と QueryDSL を組み合わせた際の LocalDate 型のパラメーターの表示のされ方について

More than 1 year has passed since last update.


概要

QueryDSL を使用してクエリを構築していますが、先日 IntelliJ IDEA 上に表示されたコンソールをみてびっくりしたので備忘録です。

なんと、LocalDate 型 のプロパティについては、UTC+9 にてパラメーターがバインドされているのです。

通常の、Spring Data JPA にて生成されたクエリについては、特段問題なくパラメーターがバインドされているようでした。


  • コンソール上の SQL


select
o.id,
o.order_id
o.purchase_date
from customer_order o
where o.purchase_date = '11/01/2020 09:00:00.000'
and o.order_id = 1


動作について

上記は (おそらく SpyLogger が) コンソール上で表示している値が UTC+9 で表示されているだけのようでした。

tail にて mysql 上のログを監視した結果、日付がバインドされていない動作になっておりました。


  • MySQL 上で記録されたログ

select 

o.id,
o.order_id,
o.purchase_date
from customer_order o
where o.purchase_date = '2020-11-01'
and o.order_id = 1


補足

上記のコンソール上の SQL において、パラメーターは MM/dd/yyyy HH:00:00.000 の形式にて出力されています。(11/01/2020 09:00:00.000)

Spring Data JPA にて生成されるクエリの場合においても、コンソール上に出力される日付の形式は、上記の形式で yyyy-MM-dd HH:00:00 にて出力されませんでした。

なお、QueryDSL については、Spring Data JPA とは異なる JSR310 のパーサーを独自で実装していますので、パラメータには時刻秒が付加されていないようでした。


JSR310LocalDateType.java

package com.querydsl.sql.types;

public class JSR310LocalDateType extends AbstractJSR310DateTimeType<LocalDate> {

public JSR310LocalDateType() {
super(Types.DATE);
}

public JSR310LocalDateType(int type) {
super(type);
}

@Override
public void setValue(PreparedStatement st, int startIndex, LocalDate value) throws SQLException {
Instant i = value.atStartOfDay(ZoneOffset.UTC).toInstant();
st.setDate(startIndex, new Date(i.toEpochMilli()), utc());
}
}


上記の実装になっているので、utc() メソッドと使用している JDBC のドライバ (PreparedStatement の実装) の相性が悪いのか、

と思いとても焦りました。

また、Spring Data JPA がクエリを構築する場合、規定のパーサでは、LocalDate 型についても、'2018-05-01 00:00:00' と、LocalDateTime の形式でパラメーターがバインドされて SQL が実行されました。


  • Spring Data JPA にてクエリが構築されて実行される SQL


select
o.id,
o.order_id
o.purchase_date
from customer_order o
where o.purchase_date = '2020-11-01 00:00:00'
and o.order_id = 1