You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot 3搭配PostgreSQL时Instant映射timestamp失败问题

Spring Boot 3(Hibernate 6.1)+ PostgreSQL 下Instant映射timestamp without time zone的问题

在Spring Boot 3(搭配Hibernate 6.1)与PostgreSQL结合使用时,将Instant值映射到SQL timestamp without time zone类型会出现问题——执行测试用例时,读取的值与写入的值相差本地时区偏移量。但切换到H2测试数据库,或者回退到Spring Boot 2.7.6(Hibernate 5.6)时,测试用例可正常通过。

JPA实体

@Entity
public class MyEntity {

  @Id
  UUID id = UUID.randomUUID();

  //@JdbcType(TimestampJdbcType.class) //临时解决方法
                                       //(替代方案:在自定义Hibernate方言中全局声明)
                                       //为何仅Spring Boot3+PostgreSQL需要此配置?
  @Column(columnDefinition = "timestamp")
  Instant createdTimestamp = Instant.now();
}

Spring Data仓库

public interface MyEntityRepository extends CrudRepository<MyEntity, UUID> {
}

JUnit集成测试

@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE) //注释此行以使用H2数据库
class MyEntityRepositoryITest {

  @Autowired
  MyEntityRepository myEntityRepository;

  @Test
  @Transactional(propagation = NOT_SUPPORTED) //不使用事务
  void readInstantSameAsPersisted() {
    var entity = new MyEntity();
    myEntityRepository.save(entity);

    var read = myEntityRepository.findById(entity.id).orElseThrow();
    assertEquals(entity.createdTimestamp.getEpochSecond(), read.createdTimestamp.getEpochSecond());
  }
}

Maven pom.xml依赖

<dependency>
  <groupId>org.postgresql</groupId>
  <artifactId>postgresql</artifactId>
  <scope>runtime</scope>
</dependency>
<dependency>
  <groupId>com.h2database</groupId>
  <artifactId>h2</artifactId>
  <scope>test</scope>
</dependency>

Spring application.properties配置

spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:postgresql://localhost:5432/dbname
spring.datasource.username=username
spring.datasource.password=password

注意事项

  • 设置spring.jpa.properties.hibernate.jdbc.time_zone无效果。
  • 不考虑切换为LocalDateTime,因为需要createdTimestamp表示明确的时间点。
  • 不考虑切换为带时区信息的SQL类型,不希望数据库中存在时区各异的值。
  • spring.datasource.hikari.connection-init-sql=SET TIME ZONE 'UTC'可作为临时解决方法,但不解为何需要此配置——读取基于1970-01-01以来秒数的值应与写入值一致,与后台时区无关。
  • pgJDBC不支持Instant,但Hibernate支持。
  • 相关Stack Overflow回答可能有关联,但为何旧版Hibernate可正常工作?

更新

某Stack Overflow回答指出,timestamp with time zone并不像名称所示携带额外时区信息,仅存储UTC时间线上的一个点,可在不同时区展示,似乎更适配此场景。

内容的提问来源于stack exchange,提问作者Knight Industries

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 18:40:56