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

Timezone issue in Spring Boot JPA application

我的 spring 引导 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

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

尽量避免在时区中使用日期作为时间戳,因为它的设计无法很好地处理这些时间。

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

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

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

不要使用传统的 class Date 而是使用现代的 class LocalDateTime

您可以尝试将 @DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX") 放在 createdOn setter 上。

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

实际上问题是因为

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 设置为 jackson 时区,这解决了问题。

希望这个回答能对某人有所帮助。

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

  • 服务器 OS 级别:sudo timedatectl set-timezone UTC(例如 Cent OS)
  • 在 MySQL / my.cnf 文件中的数据库服务器(可选)
  • Spring 配置: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 框架,您可以在实体 属性 / 字段上使用 @JsonFormat(shape= JsonFormat.Shape.STRING, pattern="dd MMM yyyy HH:mm:ss") 自动将 DateTime 值解析为字符串格式。
  • 应用程序入口点@SpringBootApplication

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

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