我有一个SpringBoot应用程序。使用Spring Initializer,嵌入式Tomcat,Thymeleaf模板引擎和包作为可执行的JAR文件。
我有一个具有2个属性的域对象(initDate,endDate)。我想创建2个转换器来处理mySQL DB
@Convert(converter = LocalDateTimeAttributeConverter.class)
private LocalDateTime initDate;
@Convert(converter = ZonedDateTimeAttributeConverter.class)
private ZonedDateTime endDate;
转换器1(可以)
@Converter
public class LocalDateTimeAttributeConverter implements AttributeConverter<LocalDateTime, Timestamp> {
@Override
public Timestamp convertToDatabaseColumn(LocalDateTime localDateTime) {
return (localDateTime == null ? null : Timestamp.valueOf(localDateTime));
}
@Override
public LocalDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
return (sqlTimestamp == null ? null : sqlTimestamp.toLocalDateTime());
}
}
这是我想要创建的
@Converter
public class ZonedDateTimeAttributeConverter implements AttributeConverter<ZonedDateTime, Timestamp> {
@Override
public Timestamp convertToDatabaseColumn(ZonedDateTime zoneDateTime) {
return (zoneDateTime == null ? null : Timestamp.valueOf(zoneDateTime));
}
@Override
public ZonedDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
return (sqlTimestamp == null ? null : sqlTimestamp.toZonedDateTime());
}
}
但我不能因为我有2个错误:
The method valueOf(String) in the type Timestamp is not applicable for the arguments (ZonedDateTime)
并且TimeStamp没有方法toZonedDateTime()
如果我没有为ZonedDate添加任何转换器,JPA会创建一个类型为varbinary(255)
答案 0 :(得分:8)
Timestamp扩展Date
以提供纳秒精度。 Date
和Timestamp
均未设计为将特定时区称为ZoneDateTime
。
如果您需要转换ZonedDateTime
- &gt; Timestamp
您必须丢弃时区/偏移信息。 E.g。
LocalDateTime withoutTimezone = zoneDateTime.toLocalDateTime();
Timestamp timestamp = Timestamp.valueOf(withoutTimezone));
并转换Timestamp
- &gt; ZonedDateTime
您需要指定一个偏移量:
LocalDateTime withoutTimezone = sqlTimestamp.toLocalDateTime();
ZonedDateTime withTimezone = withoutTimezone.atZone(ZoneId.of("+03:00"));
或时区:
ZonedDateTime withTimezone = withoutTimezone.atZone(ZoneId.of("Europe/Paris"));
如果您打算在数据库中保存ZonedDateTime
个变量并保留其中指定的各个时区,我建议您相应地设计数据库。建议:
DATETIME
类型的列保存LocalDateTime
和VARCHAR
,以保存时区,如"Europe/Paris"
或SMALLINT
,以分钟为单位保存偏移量。 ZonedDateTime
转换为String
并保存在VARCHAR
列中"2017-05-16T14:12:48.983682+01:00[Europe/London]"
。然后,您必须在从数据库中读取时解析它。答案 1 :(得分:7)
@Override
public Timestamp convertToDatabaseColumn(ZonedDateTime zoneDateTime) {
return zoneDateTime == null ? null : Timestamp.from(zoneDateTime.toInstant());
}
@Override
public ZonedDateTime convertToEntityAttribute(Timestamp sqlTimestamp) {
return sqlTimestamp == null ? null : sqlTimestamp.toInstant().atZone(ZoneId.systemDefault());
}
Jon还问了一个好问题,你想要哪个时区?我猜到了ZoneId.systemDefault()
。显然,不同的时区会产生不同的结果,所以我希望你会三思而后行,并且能够为你的目的找到合适的时区。
PS我减少了括号的使用,因为我发现它更具可读性。如果您愿意,可以将它们重新添加。