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?

+0

遗忘Spring,JDBC等的细节 - 听起来像你试图将“即时+时区”存储在只能存储瞬间的字段中......所以这不会比“I想要在4字节字段中存储32个字节的数据“会。我建议你计算出你想存储什么信息,以什么方式*然后*计算出如何实现它。 –

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到数据库。

不是我确定的最干净或最好的解决方案,但是由于无法更改数据库,驱动程序或其他方式工作的限制,它似乎表现良好。