2016-06-25 5 views
1

Каков наилучший способ преобразования java.time.Duration -объекта в java.sql.Time?Как преобразовать java.time.Duration в java.sql.Time?

Я получаю ISO8601-String, как PT15M51S и Duration.parse(String s) вполне подходит в этом случае.

Но теперь я боюсь, как получить java.sql.Time, но это в PreparedStatement с setTime(java.sql.Time time), чтобы сохранить его в моей базе данных MySQL с помощью JDBC.

Я закончил тем, что писал солитер как от org.apache.commons.lang3.time.DurationFormatUtils:

java.sql.Time.valueOf(DurationFormatUtils.formatDurationHMS(video.getDuration().toMillis()))) 

И для следующей проблемы: Как получить java.time.Duration от java.sql.Time.

ответ

1

Является ли структура базы данных фиксированной? Я думаю, TIME или TIMESTAMP, вероятно, не лучший тип данных для продолжительности. Я бы изменил тип столбца на BIGINT (aka Long) и конвертировал продолжительность в миллисекунды (или наносекунды в зависимости от ваших потребностей) с Duration.toMillis().

Если это не вариант, вы можете использовать аналогичную логику и представлять продолжительность как смещение от определенной отметки времени, например 1970-01-01T00:00:00.000Z с Duration.addTo(referenceDate) или java.sql.Time(durationInMillis). Чтобы снова получить экземпляр Duration, вам нужно будет использовать Duration.ofMillis(sqlTime.getTime()).

Это в основном варианты у вас есть:

Использование BIGINT в качестве колонного типа (предпочтительное решение):

// from java.time.Duration to java.lang.Long 
{ 
    final Duration duration = ... 
    final PreparedStatement pStmnt = con.prepareStatement("..."); 
    pStmnt.setLong(n, duration.toMillis()); 
} 

// from java.lang.Long to java.time.Duration 
{ 
    final PreparedStatement pStmnt = con.prepareStatement("..."); 
    final ResultSet resultSet = pStmnt.getResultSet(); 
    while (resultSet.next()) { 
     final Long durationInMillis = resultSet.getLong(n); 
     final Duration duration = Duration.ofMillis(durationInMillis); 
     ... 
    } 
} 

Использование TIME или TIMESTAMP как тип столбца. Вы можете заменить java.sql.Time с java.sql.Timestamp в коде ниже в зависимости от фактического типа столбца:

// from java.time.Duration to java.sql.Time(stamp) 
{ 
    final Duration duration = ... 
    final Time time = new Time(duration.toMillis()); 

    final PreparedStatement pStmnt = con.prepareStatement("..."); 
    pStmnt.setTime(n, time); 
} 

// from java.sql.Time(stamp) to java.time.Duration 
{ 
    final PreparedStatement pStmnt = con.prepareStatement("..."); 
    final ResultSet resultSet = pStmnt.getResultSet(); 
    while (resultSet.next()) { 
     final Time time = resultSet.getTime(n); 
     final Duration duration = Duration.ofMillis(time.getTime()); 
     ... 
    } 
} 

Согласно документации в MySQL TIME типа поддерживает диапазоны от -838:59:59 до 838:59:59 (см here). Но по умолчанию ни один из типов TIME, DATE или TIMESTAMP не поддерживает дробные секунды, если только заданная точность не указана во время создания столбцов базы данных (см. here). То есть для хранения миллисекунды в TIME столбце таблицы должен быть создан так:

CREATE TABLE t1 (t TIME(3)); 

Обновление:

  • Добавлено более подробные примеры кода
  • Добавлена ​​ссылка Документация MySQL относительно поддерживаемых минимальных значений для TIME
4

A java.sql.Time is не Продолжительность, это время в течение дня (т.е. обычные 24-часовые часы).Хранение длительности в нем - это взломать и взломать этот хак, если эта продолжительность больше 24 часов. Вам лучше хранить его как строку продолжительности ISO, или в виде типа данных (например, двойной или, возможно, числовой), или если ваша база данных поддерживает это: в interval.

Однако, если вы все еще хотите сохранить длительность в SQL TIME: Точка преобразования из java.time в java.sql.Time является java.time.LocalTime использованием java.sql.Time.valueOf(LocalTime). Таким образом, чтобы конвертировать из Duration в java.sql.Time вы можете сделать:

Duration duration = ..; 
LocalTime localTime = LocalTime.MIDNIGHT.plus(duration); 
java.sql.Time sqlTime = java.sql.Time.valueOf(localTime); 

Спинка преобразование будет:

java.sql.Time sqlTime = ..; 
LocalTime localTime = sqlTime.toLocalTime(); 
Duration duration = Duration.between(LocalTime.MIDNIGHT, localTime); 

Имейте в виду, что java.sql.Time может иметь только точность в секундах. При использовании драйвера JDBC 4.2 совместимость с драйвером java.sql.Time не требуется, поскольку сохранение java.time.LocalTime поддерживается напрямую с использованием setObject(1, <your LocalTime>) и getObject(1, java.time.LocalTime.class).

+0

Хотя я согласен с тем, что хранить длительность в столбце 'TIME' не рекомендуется, это не будет длиться дольше 24 часов. Я обновил свой ответ ссылкой на соответствующий раздел документации по MySQL ... – dpr

+0

@dp Интересно, я не знал этого о 'TIME' в MySQL. Однако я не думаю, что это было бы полностью поддержано через 'java.sql.Time'. –

+0

похоже - не знаю, официально ли это поддерживается. Можно создать произвольные длинные экземпляры 'java.sql.Time', используя конструктор' Time (long) '. Однако я не уверен, как это выглядит, когда речь заходит о поддержке других СУБД ... – dpr

Смежные вопросы