JPA如何在Oracle中设置CURRENT_TIMESTAMP默认值并格式化日期
你之前的配置出现小数的核心原因是Oracle默认的CURRENT_TIMESTAMP返回带6位小数秒的TIMESTAMP WITH TIME ZONE类型,同时JPA实体映射的字段没有限制精度,导致小数秒被存入数据库。以下是可直接落地的解决方案:
方案1:数据库层面控制(推荐,和MySQL逻辑一致,默认值由数据库维护)
直接通过columnDefinition显式指定Oracle兼容的字段类型和默认值,数据库层面直接截断小数秒,无需代码逻辑处理:
@CreationTimestamp @Column( name = "created_date", insertable = false, updatable = false, // Oracle的DATE类型天然精确到秒,无小数秒,SYSDATE返回当前系统时间到秒 columnDefinition = "DATE DEFAULT SYSDATE" ) protected LocalDateTime createdDate;
如果偏好使用TIMESTAMP类型,可指定精度为0:
columnDefinition = "TIMESTAMP(0) DEFAULT CURRENT_TIMESTAMP"
注意:如果你的表已经创建完成,需要先执行DDL修改现有字段属性,示例:
ALTER TABLE 你的表名 MODIFY created_date DATE DEFAULT SYSDATE;
方案2:JPA层面控制(适配多数据库场景)
如果需要兼容MySQL、Oracle多数据源,不想写数据库特定的columnDefinition,可以通过@PrePersist钩子在实体插入前手动截断时间到秒:
import java.time.temporal.ChronoUnit; import javax.persistence.PrePersist; import org.hibernate.annotations.CreationTimestamp; import org.hibernate.annotations.ColumnDefault; @CreationTimestamp @ColumnDefault("CURRENT_TIMESTAMP") @Column(name = "created_date", updatable = false) protected LocalDateTime createdDate; @PrePersist protected void onCreate() { // 手动截断纳秒部分,仅保留到秒 if (createdDate == null) { createdDate = LocalDateTime.now().truncatedTo(ChronoUnit.SECONDS); } else { createdDate = createdDate.truncatedTo(ChronoUnit.SECONDS); } }
这个方案不需要修改数据库现有字段,实体层面就保证存入的时间没有小数秒。
内容的提问来源于stack exchange,提问作者iwritecomeinmymind
相关产品推荐
相关产品推荐

