0
0

More than 3 years have passed since last update.

SpringのLocalTimeをMySQLのTimeでINSERTしたい(millisecondsも)

Last updated at Posted at 2019-11-30

概要

String型で取得した 11:12:13.14 (時間:分:秒.ミリ秒)を
MySQLにINSERTして
image.png
とミリ秒まで表示させる方法についてです。(日付情報はいらない)

そんなの普通に実装すればできそうじゃない?
って思うじゃないですか。

簡単そうに見えて面倒くさい処理を挟まないとうまくいきませんでした。。。
もっとスマートな方法をお存じの方がいましたら、教えていただけるととっても嬉しいです!!

バージョン

Spring

build.gradle
id 'org.springframework.boot' version '2.2.2.BUILD-SNAPSHOT'
sourceCompatibility = '1.8'

    runtimeOnly('mysql:mysql-connector-java')
    implementation 'org.springframework.boot:spring-boot-starter'
    implementation('org.springframework.boot:spring-boot-starter-web')
    implementation('org.springframework.boot:spring-boot-starter-data-jpa')

データベース

MySQL 8.0

ステップその1 テーブル作成

小数点3桁まで対応
MySQL :: MySQL 5.6 リファレンスマニュアル :: 11.1.2 日付と時間型の概要

create table timesample( 
    ...
    start_time TIME(3)
);

ステップその2 AttributeConverterの作成

JPA がエンティティのフィールドの型としてjava.time.LocalDate、java.time.LocalTime、java.time.LocalDateTimeは対応していないため、次のようなAttributeConverterを作成する必要があります。

package app.entities.converter;

import java.time.LocalTime;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter(autoApply = true)
public class LocalTimeConverter implements AttributeConverter<LocalTime,  java.sql.Time> {

    @Override
    public java.sql.Time convertToDatabaseColumn(LocalTime time) {
        return time == null ? null : java.sql.Time.valueOf(time);
    }

    @Override
    public LocalTime convertToEntityAttribute(java.sql.Time  value) {
        return value == null ? null : value.toLocalTime();
    }
}
Entity
    @Column(name = "start_time")
    private LocalTime startTime;
entity.setStartTime(LocalTime.of(11, 12, 13, 14*10000000));

repository.save(entity);

image.png

ミリ秒が入ってないぞ!

ステップその3 ミリ秒を保有してjava.sql.Timeに変換する

先程作成したLocalTimeConverterのconvertToDatabaseColumnメソッドを変更
spring-ミリ秒のjava.time.LocalTimeをミリ秒のjava.sql.Timeにマッピングする方法

LocalTimeConverter
package app.entities.converter;

import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalTime;

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter(autoApply = true)
public class LocalTimeConverter implements AttributeConverter<LocalTime,  java.sql.Time> {

    @Override
    public java.sql.Time convertToDatabaseColumn(LocalTime time) {
        if(time == null) return null;

        // この日付はコンバートで捨てられるので何でもOK
        long epochMilli = time.atDate(LocalDate.of(2019, 1, 1)).atZone(java.time.ZoneId.systemDefault())
                .toInstant().toEpochMilli();
        java.sql.Time sqlTime = new java.sql.Time(epochMilli);
        return sqlTime;
    }

    @Override
    public LocalTime convertToEntityAttribute(java.sql.Time  value) {
        if (value == null) return null;

        String localTimeStr = new SimpleDateFormat("HH:mm:ss.SSS").format(value);
        LocalTime localTime = LocalTime.parse(localTimeStr);
        return localTime;
    }
}

image.png

0
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0