简体   繁体   English

MyBatis + MyBatis CDI + PostgreSQL的时区问题

[英]time zone issue with MyBatis + MyBatis CDI + PostgreSQL

I have a strange time-zone issue in MyBatis. 我在MyBatis中遇到一个奇怪的时区问题。

Environment: 环境:

  • mybatis v3.4.5 mybatis v3.4.5
  • mybatis-cdi v1.0.1 mybatis-cdi v1.0.1
  • Payara app Server v4.1.2.173 Payara应用服务器v4.1.2.173
  • PostgreSQL database PostgreSQL数据库
  • JNDI datasource, MANAGED transaction setting JNDI数据源,MANAGED事务设置

At first I am inserting a record into a table where there is a date-time field. 首先,我将记录插入到有日期时间字段的表中。 On Java side it is a java.time.ZonedDateTime . 在Java方面,它是一个java.time.ZonedDateTime In the database I use TIMESTAMP WITH TIME ZONE for this field. 在数据库中,我将此字段使用TIMESTAMP WITH TIME ZONE

This is the relevant piece of code: 这是相关的代码:

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

In the logfile I can see this: 在日志文件中,我可以看到:

[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

In the database this is the result: 在数据库中,结果如下:

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

That is okay because I use GMT time zone in the database. 可以,因为我在数据库中使用GMT时区。

Then I am executing another sql insert on the same datasource with different mapper class (the POJO is different ass well), but the Java and SQL types are same. 然后,我在具有不同映射器类的同一个数据源上执行另一个sql插入(POJO也很不同),但是Java和SQL类型是相同的。 The issue is that the date-time value is inserted with GMT+2 timezone into the database instead of GMT : 问题是日期时间值是使用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

As you can see the value is inserted with wrong time-zone: 如您所见,值插入时区错误:

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

My first guess was it comes from the wrong database pool settings so I have added the following property to my pool configuration: 我的第一个猜测是它来自错误的数据库池设置,因此我在池配置中添加了以下属性:

sessionTimeZone=UTC

But I am still inserting the 1st date-time in UTC and the 2nd in UTC+2 time-zone. 但是我仍然在UTC中插入第一个日期时间,在UTC + 2时区中插入第二个日期时间。

I have tried to log out the details of the java.sql.Connection to see what a hell is going here so I injected SqlSqssion into my code (@Inject SqlSession sqlSession) but of course I got a org.apache.ibatis.session.SqlSessionException: Error: Cannot get connection. No managed session is started.. 我试图注销java.sql.Connection的详细信息以了解到底发生了什么,所以我将SqlSqssion注入了我的代码中(@Inject SqlSession sqlSession),但是当然我得到了org.apache.ibatis.session.SqlSessionException: Error: Cannot get connection. No managed session is started.. org.apache.ibatis.session.SqlSessionException: Error: Cannot get connection. No managed session is started.. exception because I use MANAGED transaction handling. org.apache.ibatis.session.SqlSessionException: Error: Cannot get connection. No managed session is started..异常,因为我使用MANAGED事务处理。

Any idea what to check? 知道要检查什么吗?

----- UPDATE 1 ----- -----更新1 -----

So I changed everything to UTC as per the suggestion: 所以我按照建议将所有内容更改为UTC:

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

It seems okay, BUT... 看来还可以,但是...

When I execute my query in PostgreSQL console this is the result: 当我在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)

Same query result in SqurielSQL: SqurielSQL中的查询结果相同:

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

It seems that my SQL client does some tricky timezone conversation at the background but I am not sure. 看来我的SQL客户端在后台进行了一些棘手的时区对话,但我不确定。 I need to check it. 我要检查一下

----- UPDATE 2 ----- -----更新2 -----

I am not sure what was the problem but my issue was solved after I have changed the database and JVM timezone setting to UTC. 我不确定是什么问题,但是在将数据库和JVM时区设置更改为UTC之后,我的问题已解决。

I use the following SQL query to get back the stored date-time value from database: 我使用以下SQL查询从数据库中获取存储的日期时间值:

SELECT current_timestamp AT TIME ZONE 'UTC'

I would set everything at UTC to make everything simpler. 我会在UTC设置所有内容,以使其变得更简单。

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

If it displays anything else than UTC, then add VM argument -Duser.timezone=UTC to the application startup. 如果显示的不是UTC,则将VM参数-Duser.timezone=UTC添加到应用程序启动中。

There is a confusion in the snippet variables request / httpRequest , maybe just a typo ? 代码段变量request / httpRequest有一个混淆,也许只是拼写错误?

request .setRequestDate = ZonedDateTime.now(); request .setRequestDate = ZonedDateTime.now();

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM