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")); }
这应该涵盖处理日期和时间戳时遇到的大部分实施挑战。希望对你有帮助。
我的 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")); }
这应该涵盖处理日期和时间戳时遇到的大部分实施挑战。希望对你有帮助。