【问题标题】:time zone issue with MyBatis + MyBatis CDI + PostgreSQLMyBatis + MyBatis CDI + PostgreSQL 的时区问题
【发布时间】:2018-03-30 16:15:18
【问题描述】:

我在 MyBatis 中有一个奇怪的时区问题。

环境:

  • mybatis v3.4.5
  • mybatis-cdi v1.0.1
  • Payara 应用服务器 v4.1.2.173
  • PostgreSQL 数据库
  • JNDI 数据源,托管事务设置

起初我将一条记录插入到有日期时间字段的表中。 在 Java 方面,它是 java.time.ZonedDateTime。在数据库中,我为此字段使用TIMESTAMP WITH TIME ZONE

这是相关的代码:

request.setRequestDate = ZonedDateTime.now();
LOGGER.info("xxx-xxx-xxx: " + httpRequest.getRequestDate());
myMapper.save(request);

在日志文件中我可以看到:

[INFO ] 2017-10-18 18:43:45,501 com..................... - xxx-xxx-xxx: 2017-10-18T18:43:45.493+02:00[Europe/Prague]
[DEBUG] 2017-10-18 18:43:45,608 com...xxxDao.saveRequest - ==>  Preparing: INSERT INTO table_a (id, ..., request_date) VALUES (?, ?, ...) 
[DEBUG] 2017-10-18 18:43:45,770 com...xxxDao.saveRequest - ==> Parameters: 281(Long), ..., 2017-10-18 16:43:45.493(Timestamp)
[DEBUG] 2017-10-18 18:43:45,783 com...xxxDao.saveRequest - <==    Updates: 1

在数据库中这是结果:

select request_date from table_a
result: 2017-10-18 16:43:45.493

没关系,因为我在数据库中使用 GMT 时区。

然后我正在使用不同的映射器类(POJO 也不同)在同一数据源上执行另一个 sql 插入,但 Java 和 SQL 类型是相同的。问题是日期时间值与GMT+2 时区一起插入数据库而不是GMT

[INFO ] 2017-10-18 18:43:46,188 com..................... - yyy-yyy-yyy: 2017-10-18T18:43:46.188+02:00[Europe/Prague]
[DEBUG] 2017-10-18 18:43:46,190 com...yyyDao.saveMetadata - ==>  Preparing: INSERT INTO table_b (id,..., uploaded) VALUES (?, ?, ...) 
[DEBUG] 2017-10-18 18:43:46,202 com...yyyDao.saveMetadata - ==> Parameters: 561(Long), ..., 2017-10-18 18:43:46.188(Timestamp)
[DEBUG] 2017-10-18 18:43:46,212 com...yyyDao.saveMetadata - <==    Updates: 1

如您所见,插入的值是错误的时区:

select uploaded from table_b
result: 2017-10-18 18:43:46.188

我的第一个猜测是它来自错误的数据库池设置,因此我在池配置中添加了以下属性:

sessionTimeZone=UTC

但我仍然在 UTC 中插入第一个日期时间,在 UTC+2 时区中插入第二个日期时间。

我试图注销 java.sql.Connection 的详细信息以查看到底发生了什么,所以我将 SqlSqssion 注入我的代码 (@Inject SqlSession sqlSession) 但当然我得到了 org.apache.ibatis.session.SqlSessionException: Error: Cannot get connection. No managed session is started.. 异常,因为我使用 MANAGED 事务处理。

知道要检查什么吗?

-- 更新 1 -----

所以我按照建议将所有内容都更改为 UTC:

  • postgresql.conf:时区 = 'UTC'
  • 应用服务器:-Duser.timezone=UTC

看起来不错,但是……

当我在 PostgreSQL 控制台中执行查询时,结果如下:

demo=# select EXTRACT(TIMEZONE FROM uploaded), uploaded from image_metadata;
 date_part |          uploaded
-----------+----------------------------
         0 | 2017-10-25 00:24:11.873+00
(1 row)

SqurielSQL 中相同的查询结果:

date_part   uploaded
0           2017-10-25 02:24:11.873

我的 SQL 客户端似乎在后台进行了一些棘手的时区对话,但我不确定。我需要检查一下。

-- 更新 2 -----

我不确定是什么问题,但在我将数据库和 JVM 时区设置更改为 UTC 后,我的问题得到了解决。

我使用以下 SQL 查询从数据库中取回存储的日期时间值:

SELECT current_timestamp AT TIME ZONE 'UTC'

【问题讨论】:

  • 是的,默认情况下,每个客户端(包括 java)都将使用本地系统时区,除非另一个值被明确指定为连接 url 中的选项(取决于数据库供应商)或通过诸如 [set会话时区] (postgresql.org/docs/current/static/sql-set.html)

标签: java postgresql mybatis ibatis mybatis-cdi


【解决方案1】:

我会将一切设置为 UTC,以使一切变得更简单。

LOGGER.info(TimeZone.getDefault().getID())

如果它显示的不是 UTC,则将 VM 参数 -Duser.timezone=UTC 添加到应用程序启动中。

sn-p 变量request / httpRequest 有混淆,可能只是一个错字?

请求.setRequestDate = ZonedDateTime.now();

LOGGER.info("xxx-xxx-xxx: " + httpRequest.getRequestDate());

【讨论】:

  • 那只是一个错字,抱歉。我的 SQL 客户端似乎做了一些意想不到的事情。请查看帖子中的更新信息。
猜你喜欢
  • 1970-01-01
  • 2016-06-15
  • 2014-02-15
  • 2011-09-01
  • 1970-01-01
  • 2022-11-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多