我在"欧洲/伦敦"有一个数据库服务器。时区和我的网络服务器在" Europe / Brussels"。由于现在是夏天,我的应用程序服务器有两个小时的差异。
我创建了一个测试来重现我的问题:
Query q = JPA.em().createNativeQuery("SELECT UNIX_TIMESTAMP(startDateTime) FROM `Event` WHERE `id` =574");
BigInteger unix = (BigInteger) q.getSingleResult();
System.out.println(unix + "000 UNIX_TIMESTAMP to BigInteger");
Query q2 = JPA.em().createNativeQuery("SELECT startDateTime FROM `Event` WHERE `id` =574");
Timestamp o = (Timestamp) q2.getSingleResult();
System.out.println(o.getTime() + " Timestamp");
startDateTime列定义为' datetime' (但是' timestamp'同样的问题) 我得到的输出是:
1340291591000 UNIX_TIMESTAMP to BigInteger
1340284391000 Timestamp
读取java日期对象会导致时区发生变化,我该如何解决这个问题?我希望jdbc驱动程序只设置" unix时间"它从Date对象中的服务器获取的值。
(适当的解决方案应该适用于任何时区组合,不仅适用于GMT中的db)
答案 0 :(得分:1)
JDBC驱动程序正在使用运行它的JVM的时区设置。如果您在Europe / Brussels运行应用程序,它会假定时区。如果您的数据库服务器在另一个时区运行,则使用Java进行的计算结果可能与SQL中的计算结果不同。
答案 1 :(得分:1)
您可以设置MySQL Timestamp列类型和:
<bean id="dataSource" class="com.jolbox.bonecp.BoneCPDataSource" destroy-method="close">
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="username" value="${jdbc.user}"/>
<property name="password" value="${jdbc.pass}"/>
<property name="idleConnectionTestPeriodInMinutes" value="60"/>
<property name="idleMaxAgeInMinutes" value="240"/>
<property name="maxConnectionsPerPartition" value="30"/>
<property name="minConnectionsPerPartition" value="10"/>
<property name="partitionCount" value="3"/>
<property name="acquireIncrement" value="5"/>
<property name="statementsCacheSize" value="100"/>
<property name="initSQL" value="SET time_zone='${database.timezone}'"/>
这是我的bonecp dataSource - &gt;看到initSQL这个查询是在每个mysql连接的init上执行的。如果您的Web服务器位于Europe / Brussels,请将此时区设置为$ {database.timezone},这对我有用。 如果你的mysql有空的时区表,你需要从Linux语言环境中导入它,如:
mysql_tzinfo_to_sql / usr / share / zoneinfo | mysql -u root -p mysql
答案 2 :(得分:0)
我能够使用连接字符串参数
解决此问题useJDBCCompliantTimezoneShift=true&useSSPSCompatibleTimezoneShift=true
但我对此并不十分满意,因为当数据库不在UTC / GMT时区时会造成更多麻烦。