JPA 更新日期时间戳

Posted

技术标签:

【中文标题】JPA 更新日期时间戳【英文标题】:JPA update date timestamp 【发布时间】:2019-04-23 15:13:11 【问题描述】:

每当我使用 JPA 插入或更新实体时,我想在数据库 systimestamp 值上设置更新日期列。注意我要使用数据库节点的时间,而不是应用服务器的时间。 JPA 或 EclipseLink 注释可以做到这一点吗?

【问题讨论】:

【参考方案1】:

some JPA providers 支持这样的功能,遗憾的是 Eclipselink 不是其中之一。

幸运的是,自定义的 EclipseLink 属性转换器机制允许您在转换期间访问Session,因此以下解决方法有效:

@Converter(name = "database-timestamp", converterClass = DatabaseTimestampFieldConverter.class)
@Entity
public class AuditedEntity 

    @Id
    @GeneratedValue
    private Long id;
    private String name;
    ... 

    @Convert("database-timestamp")
    private Timestamp updatedDate;

    @PreUpdate
    protected void preUpdate() 
        updatedDate = null; // needed to trigger the conversion; if you don't want the extra method here, use @EntityListeners instead
    

其中DatabaseTimestampFieldConverter定义为:

public class DatabaseTimestampFieldConverter implements Converter 

    @Override
    public Object convertObjectValueToDataValue(Object objectValue, Session session) 
        return session.executeQuery(new ValueReadQuery("SELECT CURRENT_TIMESTAMP"));
    

    @Override
    public Object convertDataValueToObjectValue(Object dataValue, Session session) 
        return dataValue;
    

    @Override
    public boolean isMutable() 
        return true;
    

    @Override
    public void initialize(DatabaseMapping mapping, Session session) 

    


或者,您可以尝试在 auditing example from the docs 之上构建。不过,它使用硬编码的数据库列名而不是字段级注释。

当然,使用您的数据库提供的机制(例如触发器)可能是一种性能更高的解决方案。

【讨论】:

那是一些丑陋的样板 好吧,@Convert("database-timestamp") 可以跨多个实体重用(您只能在一个实体上定义@Converter),并且preUpdate() 可以替换为@EntityListeners(不幸的是,您将需要@EntityListeners每个被审计单位)。恐怕这是最接近使用 EclipseLink 的纯基于注释的解决方案了【参考方案2】:

您可以使用CURRENT_DATE | CURRENT_TIME | CURRENT_TIMESTAMP 获取数据库时间

【讨论】:

在哪里使用? @Query注解中 ***.com/a/31743471/496099 提到它是一个有效的 JPQL 函数 en.wikibooks.org/wiki/Java_Persistence/JPQL#Functions @Query(value="update e set e.lastUpdateTime=CURRENT_TIMESTAMP")

以上是关于JPA 更新日期时间戳的主要内容,如果未能解决你的问题,请参考以下文章

在 Oracle 时间戳列中以 UTC 保存日期

如何在时间戳字段中仅使用日期来选择记录?

时间戳、行版本和日期时间 - 插入或更新行时我需要一个标记

Hibernate/JPA - 使用@Future 更新还包含日期字段的实体字段

如何使用 sysdate 更新日期列,包括动态 sql 中的时间戳

将日期时间列值批量转换和更新为 UNIX 时间戳?