Spring Boot JPA 应用程序中的时区问题

问题描述 投票:0回答:5

我在 Spring Boot jpa 应用程序中面临日期时间问题。

例如,在我的数据库中,我有一列

created_on
其中包含
2019-07-11 09:30:00
日期。 当我通过 JPA 获取此记录时,它会转换为 UTC。
例如,它将
2019-07-11 09:30:00
转换为
2019-07-11 05:00:00

我的系统时间在 IST 中,日期也保存在 IST 的数据库中。

我使用的是mysql数据库。

在我的实体中

private Date createdOn;

数据库栏目:

created_on timestamp

服务:

@Service
@Transactional(readOnly = true)
public class EntityTypeService {
  @Autowired
  private IEntityTypeRepository entityTypeRepository;

  public EntityType findById(Long id) {
    EntityType entityType = entityTypeRepository.findById(id).orElse(new EntityType());
    System.out.println(entityType.getCreatedOn());
    return entityType;
  }
}

存储库

@Repository
public interface IEntityTypeRepository extends CrudRepository<EntityType, Long> {
}

数据库中的日期是

2019-07-11 09:30:00

但是当我在服务上打印它时

System.out.println(entityType.getCreatedOn());
它给了我
2019-07-11 05:00:00

这是我整个应用程序中的普遍问题。

mysql spring-boot hibernate jpa timezone
5个回答
7
投票

经过大量研究,我找到了解决方案。

其实问题是因为

spring.jpa.properties.hibernate.jdbc.time_zone=UTC

这个属性是我在我的

appication.properties
中设置的。

当我删除此属性时,后端一切正常。后端显示数据库中可用的完美时间。

但是现在当响应到达前端时,那时我的日期会转换为 UTC。

与后端一样,它显示

2020-06-03 18:56:14.0
,而当涉及前端时,它会转换为
2020-06-02T13:26:14.000+0000

这对我来说也是一个问题。

因此,经过更多研究,我发现当对象发送到前端时,

Jackson
默认将所有日期转换为 UTC。

这个问题的解决办法是

spring.jackson.time-zone=IST

我的数据库和系统时区是 IST,所以我也将 IST 设置为杰克逊时区,这解决了问题。

希望这个答案可以帮助别人。


4
投票

在后端应用程序使用 JPA + Spring Boot 时,请确保在整个服务器配置中使用相同的时区。例如,要使用 UTC,请执行以下操作:

  • 在服务器操作系统级别:
    sudo timedatectl set-timezone UTC
    (例如在 Cent 操作系统上)
  • 在 MySQL / 数据库服务器上的
    my.cnf
    文件中(可选)
  • 弹簧配置:
    spring.jpa.properties.hibernate.jdbc.time_zone=UTC
  • MySQL URL 查询参数
    spring.datasource.url=jdbc\:mysql\://localhost\:3306/my_db_name?useUnicode=true&characterEncoding=utf8&serverTimezone=UTC&useLegacyDatetimeCode=false 
  • 如果您使用 Jackson JSON 框架,您可以使用实体属性/字段上的
    DateTime
    自动将
    @JsonFormat(shape= JsonFormat.Shape.STRING, pattern="dd MMM yyyy HH:mm:ss")
    值解析为字符串格式。
  • 应用入口点
    @SpringBootApplication

@PostConstruct public void init(){ TimeZone.setDefault(TimeZone.getTimeZone("UTC")); }

这应该涵盖处理日期和时间戳时的大部分实施挑战。希望有帮助。


2
投票

您可以使用

serverTimezone
设置数据库连接的时区,例如:
Asia/Kolkata
并使用
useLegacyDatetimeCode=false

spring.datasource.url= = jdbc:mysql://127.0.0.1/db_name?useLegacyDatetimeCode=false&serverTimezone=Asia/Kolkata

并且不要使用遗留类

Date
而是使用现代类
LocalDateTime


0
投票

尽量避免使用 Date 作为时区时间戳,因为它的设计不能很好地处理这些问题。

您可以尝试使用 formatter 打印日期对象,或者使用 LocalDateTime(如果时区对您很重要,则使用 ZonedDateTime)。


0
投票

您可以尝试将

@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX")
放在
createdOn
设置器上。

© www.soinside.com 2019 - 2024. All rights reserved.