我在Stack Overflow和邮件列表上找到了很多文章,记录了MySQL JDBC在时区、日期时间等方面的问题。但即使如此,我仍然无法解决这个问题。
jdbc:mysql://localhost:3306/BigSense?useLegacyDatetimeCode=false&serverTimezone=UTC
我使用以下格式插入日期:
stmt.setTimestamp(x, s, Calendar.getInstance(TimeZone.getTimeZone("UTC")))
而且日期确实正确地存储在MySQL中的一个UTC时间的DateTime列中。我可以从控制台执行SELECT,并以我发送给服务器的时间格式查看它。问题是当我在Java/JDBC中执行SELECT时,由于某种原因,它将其转换为我的本地时区!我使用的Scala代码如下:
using(stmt.getResultSet()) {
ret =>
if (ret != null) {
val meta = ret.getMetaData()
var retbuf = new ListBuffer[Map[String, Any]]()
while (ret.next) {
val rMap = scala.collection.mutable.Map[String, Any]()
for (i <- 1 to meta.getColumnCount()) {
rMap += (meta.getColumnLabel(i) -> ret.getObject(i))
}
这是旧的Scala代码,所以不要批评我。我意识到我不应该使用retval,还有更多的“Scala”方法来编写:)
无论如何,我已经尝试了变化,我检查,看看它是否是专门的“时间”列,并使用getTimestamp代替,无论有或没有日历对象选项,我仍然得到时间转换为本地!
这是我在BigSense项目中尝试支持多个数据库(目前完全支持Postgres和MS SQL),因此我尝试尽可能保持代码的通用性/不可知性。
https://github.com/sumdog/BigSense/blob/master/src/main/scala/io/bigsense/db/DataHandlerTrait.scala
哦,我还尝试了以下方法:
noTimezoneConversionForTimeType=true
我的本地机器设置为NZST,所以如果我从JDBC URL中遗漏了“serverTimezone=UTC”,它会抱怨。插入工作正常,是返回的SELECT在不应该转换的时候转换了。
2条答案
按热度按时间qojgxg4l1#
Java时间的东西很奇怪,时间戳没有一个时区可以设置......但是它们有一个时区偏移......这会影响到toString......但是这是不能改变的......除非转换成一个字符串,然后再转换回来。
Joda-time似乎解决了其中的一些问题,但也需要一点时间来实现,而且我确信它会导致更多的问题。
我的PostgreSQL和Microsoft SQL JDBC驱动程序根本不向返回的Timestamp添加时区,而MySQL会添加时区(或者至少添加一个偏移量,影响toString呈现Timestamp的方式)。
这是相当丑陋的,而且是因为非标准的和有点bug/技术债务缠身的MySQL JDBC实现。
8gsdolmq2#
JVM是这样设置的,任何从数据库中获取的“日期-时间”对象,它都会将该对象转换为相应的本地日期和时间。
假设您的数据库中有一个带Zone Column的Timestap,并且它设置为MST时间,那么如果我正在运行我的应用程序India,那么每当应用程序使用Spring Data JPA或JDBC模板从数据库中获取数据时,它将向该日期-时间数据添加12小时30分钟,因此它将产生一个大混乱。
如果您使用的是Sping Boot 应用程序,那么请使用以下代码。您需要将应用程序设置在与数据库“Timestamp”列相同的时区中:-
在这里,在执行Sping Boot 应用程序之前运行
init()
方法非常重要,您也可以将此函数放在Config类中,该类可用于JPA,但不用于JDBC模板。