jooq转换器:从java.sql.Date到java.time.LocalDate
我曾尝试编写一个jooq转换器:从java.sql.Date到java.time.LocalDate,java,sql,jdbc,jooq,java-time,Java,Sql,Jdbc,Jooq,Java Time,我曾尝试编写一个转换器,但无法使其与所有时区设置一起工作 这个想法: 如果客户机代码具有LocalDate,例如2014年8月20日,并将其保存到数据库中,则无论客户机时区是什么,它在数据库中都应显示为2014年8月20日 如果DB包含2014年8月20日的日期,则客户应收到2014年8月20日的本地日期,无论客户时区是什么 我的测试: @Test public void dateConverter() { for (int offset = -12; offset <= 12;
转换器
,但无法使其与所有时区设置一起工作
这个想法:
- 如果客户机代码具有
,例如2014年8月20日,并将其保存到数据库中,则无论客户机时区是什么,它在数据库中都应显示为2014年8月20日LocalDate
- 如果DB包含2014年8月20日的日期,则客户应收到2014年8月20日的本地日期,无论客户时区是什么
@Test public void dateConverter() {
for (int offset = -12; offset <= 12; offset++) {
TimeZone localTz = TimeZone.getTimeZone(ZoneOffset.ofHours(offset));
TimeZone.setDefault(localTz);
LocalDate ld = LocalDate.now();
sql.insertInto(DATE_TEST).set(new DateTestRecord(ld)).execute();
LocalDate savedLd = sql.selectFrom(DATE_TEST).fetchOne(DATE_TEST.DATE_);
assertEquals(savedLd, ld, "offset=" + offset);
sql.delete(DATE_TEST).execute();
}
}
@Test public void dateConverter(){
对于(int offset=-12;offset问题实际上在测试中!JDBC驱动程序在创建时区时将其缓存,而测试循环中的时区更新未被考虑。每次测试中时区发生更改时,都使用新连接使其通过
因此,问题中的代码适用于Date-to-LocalDate转换器(除了它应该接受null之外)。最终版本:
public class DateConverter implements Converter<Date, LocalDate> {
@Override public LocalDate from(Date date) { return date == null ? null : date.toLocalDate(); }
@Override public Date to(LocalDate ld) { return ld == null ? null : Date.valueOf(ld); }
@Override public Class<Date> fromType() { return Date.class; }
@Override public Class<LocalDate> toType() { return LocalDate.class; }
}
公共类DateConverter实现转换器{
@重写公共LocalDate from(Date-Date){return Date==null?null:Date.toLocalDate();}
@将公共日期重写为(LocalDate ld){return ld==null?null:Date.valueOf(ld);}
@重写公共类fromType(){return Date.Class;}
@重写公共类toType(){return LocalDate.Class;}
}
时区到偏移时间转换器的时间可以采用类似的方式进行:
public class TimeConverter implements Converter<Time, OffsetTime> {
@Override public OffsetTime from(Time time) {
return time == null ? null : OffsetTime.ofInstant(Instant.ofEpochMilli(time.getTime()), ZoneOffset.systemDefault());
}
@Override public Time to(OffsetTime offsetTime) {
return offsetTime == null ? null : new Time(offsetTime.atDate(LocalDate.ofEpochDay(0)).toInstant().toEpochMilli());
}
@Override public Class<Time> fromType() { return Time.class; }
@Override public Class<OffsetTime> toType() { return OffsetTime.class; }
}
公共类TimeConverter实现转换器{
@覆盖公共偏移时间自(时间){
返回时间==null?null:OffsetTime.ofInstant(Instant.ofEpochMilli(time.getTime()),ZoneOffset.systemDefault());
}
@将公共时间覆盖到(OffsetTime OffsetTime){
return offsetTime==null?null:新时间(offsetTime.atDate(LocalDate.ofEpochDay(0)).toInstant().toEpochMilli());
}
@重写公共类fromType(){return Time.Class;}
@重写公共类toType(){return OffsetTime.Class;}
}
“JDBC驱动程序缓存时区”:嗯,什么JDBC驱动程序会这样做?注意,在上有一个关于带时区的时间戳的数据类型的持续讨论。我无法获得一个类似的转换器,与时间戳工作-可能相关?(这是postgres最新的驱动程序)是的,这肯定是相关的。你确定JDBC驱动程序真的缓存了时区吗?我希望驱动程序在建立连接时使用当前默认时区,并为连接设置该时区。在连接客户端使用SET TIME ZONE等更改时区之前,此时区设置保持有效。在这种情况下,仅更改JRE的默认时区不会影响到与DB的已建立连接和会话,但该时区根本不会被缓存。只是在建立会话期间,驱动程序会与当前时区通信,然后由连接客户端根据需要更改时区。否则e驱动程序只会以一种不可预测的方式使用您的会话进行“东西”通信和发送命令。我想如果您也使用数据库客户端的命令更改会话时区,您的测试就会成功。
public class TimeConverter implements Converter<Time, OffsetTime> {
@Override public OffsetTime from(Time time) {
return time == null ? null : OffsetTime.ofInstant(Instant.ofEpochMilli(time.getTime()), ZoneOffset.systemDefault());
}
@Override public Time to(OffsetTime offsetTime) {
return offsetTime == null ? null : new Time(offsetTime.atDate(LocalDate.ofEpochDay(0)).toInstant().toEpochMilli());
}
@Override public Class<Time> fromType() { return Time.class; }
@Override public Class<OffsetTime> toType() { return OffsetTime.class; }
}