将java.time.Duration
- 对象转换为java.sql.Time
的最佳方式是什么?
我得到的是像PT15M51S
这样的ISO8601字符串,Duration.parse(String s)
非常适合这种情况。
但现在我正在努力如何使用java.sql.Time
将PreparedStatement
转换为setTime(java.sql.Time time)
,并使用JDBC将其存储在我的MySQL数据库中。
我最后写了一封来自org.apache.commons.lang3.time.DurationFormatUtils
的绦虫:
java.sql.Time.valueOf(DurationFormatUtils.formatDurationHMS(video.getDuration().toMillis())))
对于下一个问题:如何从java.time.Duration
获取java.sql.Time
。
答案 0 :(得分:4)
java.sql.Time
不持续时间,是一天内的时间(即正常的24小时制)。在其中存储持续时间是一种黑客攻击,如果持续时间超过24小时,黑客将会中断。最好将其存储为ISO持续时间字符串,或者以数字数据类型(例如,双精度或数字)存储,或者如果数据库支持它:在interval
中。
但是,如果您仍希望将持续时间存储在sql TIME
中:使用java.sql.Time.valueOf(LocalTime)
,java.time
到java.sql.Time
的转换点为java.time.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)
。
答案 1 :(得分:1)
数据库结构是否已修复?我认为TIME
或TIMESTAMP
可能不是持续时间最佳的数据类型。我会将列类型更改为BIGINT
(又名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));
<强>更新强>
TIME