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 以上是关于JPA 更新日期时间戳的主要内容,如果未能解决你的问题,请参考以下文章
Hibernate/JPA - 使用@Future 更新还包含日期字段的实体字段