Spring JDBC Persist ZonedDateTime
问题描述:
我正在使用终端在不同时区可访问的Web门户的时钟输入/输出功能。Spring JDBC Persist ZonedDateTime
我正在使用ZonedDateTime来处理计算什么日期时间应该是给定的冲入/出记录。
// Get store timezone
ZoneId storeTimeZone = this.storeService.getStoreZoneId(storeNum);
// Get current store time to use for punch in/out timestamp
ZonedDateTime currentStoreTime = ZonedDateTime.ofInstant(Instant.now(), storeTimeZone);
当我将数据保存到Oracle 11g时,我无法保存ZonedDateTime对象。可能不受JDBC驱动程序支持。它的企业环境使数据库和驱动程序不会改变。
当我构建MapSqlParamSource传入NamedParameterJdbcTemplate时,我不得不将它转换为java.sql.Timestamp,但后来我失去了区域数据并存储了服务器所在时区的时间戳,需求指示它必须在存储时间内存储在数据库中,这只是一个Oracle TIMESTAMP列。
params.addValue("clockInTimestamp", Timestamp.from(prevRecord.getTimeEntryTimestamp().toInstant()), Types.TIMESTAMP);
有没有办法来完成这种持续的ZonedDateTime?
答
Sprint Boot项目会自动加载jsr310jpaconverters
,但这只会处理LocalDateTime
类型的转换,而不是ZonedDateTime
。如果你不使用Spring Boot,你可以自己加载这些额外的转换器。
您可能希望调整您的应用程序,以便在数据库交互级别使用这些应用程序,并将您保存的所有内容都强制置于一个标准时区,因此如果需要用户显示,您可以轻松转换为ZonedDateTime
。
答
我能够通过将ZonedDateTime转换为Instant,然后使用时区偏移手动计算时间戳来解决此问题。
实施例以下代码:
ZonedDateTime timeEntry = ZonedDateTime.now();
ZoneOffset storeOffset = timeEntry.getOffset();
ZoneOffset serverOffset = ZonedDateTime.now().getOffset();
int secondsOffset = storeOffset.getTotalSeconds() - serverOffset.getTotalSeconds();
Instant entryTimestamp = timeEntry.toInstant().plusSeconds(secondsOffset);
Timestamp ts = Timestamp.from(entryTimestamp);
然后我存留的java.sql.Timestamp到数据库。
不是我确定的最干净或最好的解决方案,但是由于无法更改数据库,驱动程序或其他方式工作的限制,它似乎表现良好。
遗忘Spring,JDBC等的细节 - 听起来像你试图将“即时+时区”存储在只能存储瞬间的字段中......所以这不会比“I想要在4字节字段中存储32个字节的数据“会。我建议你计算出你想存储什么信息,以什么方式*然后*计算出如何实现它。 –