我正在尝试使用Hibernate和JPA来持久化java.time.LocalDateTime
。我使用了Jadira Framework(" org.jadira.usertype:usertype.core:3.2.0.GA"&" org.jadira.usertype:usertype.extended:3.2.0.GA&#34 )。我创建了package-info.java
文件并在那里创建了@TypeDefs({@TypeDef(defaultForType = java.time.LocalDateTime.class, typeClass = org.jadira.usertype.dateandtime.threeten.PersistentLocalDateTime.class)})
。我测试了解决方案,java.time.LocalDateTime
字段在DATETIME
列(几乎)中正确存储/检索到我的MySQL数据库。
唯一的问题是数据库中的值与Java中字段的正确时间值相差+2小时。我在CEST(UTC + 2),所以我明白这是时区的一些问题。我调试了PersistentLocalDateTime
的代码,这就是我找到的。
PersistentLocalDateTime
正在使用org.jadira.usertype.dateandtime.threeten.columnmapper.AbstractTimestampThreeTenColumnMapper
AbstractTimestampThreeTenColumnMapper
默认情况下将字段ZoneOffset databaseZone
设置为ZoneOffset.of("Z")
(UTC)。我发现可以向@TypeDef
添加参数,因此我将其指定如下:
@TypeDef(defaultForType = LocalDateTime.class, typeClass = PersistentLocalDateTime.class,
parameters = {
@Parameter(name = "databaseZone", value = "+02:00")
}),
但我有一个例外:
java.lang.IllegalStateException: Could not map Zone +02:00 to Calendar
at org.jadira.usertype.dateandtime.threeten.columnmapper.AbstractTimestampThreeTenColumnMapper.getHibernateType(AbstractTimestampThreeTenColumnMapper.java:59)
我调试了一点。 AbstractTimestampThreeTenColumnMapper
有两种方法:
public final DstSafeTimestampType getHibernateType() {
if (databaseZone == null) {
return DstSafeTimestampType.INSTANCE;
}
Calendar cal = resolveCalendar(databaseZone);
if (cal == null) {
throw new IllegalStateException("Could not map Zone " + databaseZone + " to Calendar");
}
return new DstSafeTimestampType(cal);
}
private Calendar resolveCalendar(ZoneOffset databaseZone) {
String id = databaseZone.getId();
if (Arrays.binarySearch(TimeZone.getAvailableIDs(), id) != -1) {
return Calendar.getInstance(TimeZone.getTimeZone(id));
} else {
return null;
}
}
getHibernateType
方法抛出异常,因为resolveCalendar
方法返回null
。为什么它会返回null
?由于java.time.ZoneOffset
和java.util.TimeZone
的时区ID不匹配。据我所知,匹配的唯一可能值是Z
。任何其他值都会导致异常。
有没有办法正确设置?或者它是Jadira框架中的错误?
答案 0 :(得分:1)
它看起来像一个严重的错误。问题是jadira.usertype.databaseZone参数被解析为ZoneOffset而不是ZoneId。这样,resolveCalendar方法比较了2种不同类型的Zone和Offset。有趣的是,参数名为databaseZone,但它不包含zone。它只包含偏移量。