标签:postgresql jpa hibernate timestamp java
我的Postgres数据库中有一个带有时间戳列的表.我希望每次更新一行时自动插入它.我写了一个数据库触发器:
CREATE FUNCTION update_last_edit_date() RETURNS trigger AS $update_last_edit_date$
BEGIN
NEW.last_edit_date := localtimestamp(0);
RETURN NEW;
END;
$update_last_edit_date$LANGUAGE plpgsql;
CREATE TRIGGER update_last_edit_date BEFORE UPDATE ON employee
FOR EACH ROW
WHEN (OLD.* IS DISTINCT FROM NEW.*)
EXECUTE PROCEDURE update_last_edit_date();
哪个工作正常,但我想知道是否可以使用jpa / hibernate注释来进行此操作.我尝试了以下不同的选择:
@预更新
@PreUpdate
private void onUpdate(){
this.lastEditDate = new Date();
}
@UpdateTimestamp
@UpdateTimestamp
@Temporal(TemporalType.TIMESTAMP)
private Date lastEditDate;
但是我得到的是,当我更新一行时,所有行的时间戳都会更新,因此表中的所有时间戳始终是相同的.我在这里做错了什么?
解决方法:
有很多方法可以实现这一目标.
@EntityListener
如this article中所述,您可以使用@Embeddable存储审核属性:
@Embeddable
public class Audit {
@Column(name = "created_on")
private LocalDateTime createdOn;
@Column(name = "updated_on")
private LocalDateTime updatedOn;
//Getters and setters omitted for brevity
}
这需要一个如下所示的EntityListener:
public class AuditListener {
@PrePersist
public void setCreatedOn(Auditable auditable) {
Audit audit = auditable.getAudit();
if(audit == null) {
audit = new Audit();
auditable.setAudit(audit);
}
audit.setCreatedOn(LocalDateTime.now());
}
@PreUpdate
public void setUpdatedOn(Auditable auditable) {
Audit audit = auditable.getAudit();
audit.setUpdatedOn(LocalDateTime.now());
}
}
您的实体将必须实现审核接口:
public interface Auditable {
Audit getAudit();
void setAudit(Audit audit);
}
实体看起来像这样:
@Entity(name = "Tag")
@Table(name = "tag")
@EntityListeners(AuditListener.class)
public class Tag implements Auditable {
@Id
private String name;
@Embedded
private Audit audit;
//Getters and setters omitted for brevity
}
这是一个非常优雅的解决方案,因为它从主实体映射中提取了审计逻辑.
@PrePersist和@PreUpdate
正如我在this article中所述,您还可以使用@PrePersist和@PreUpdate JPA批注:
@Embeddable
public class Audit {
@Column(name = "created_on")
private LocalDateTime createdOn;
@Column(name = "updated_on")
private LocalDateTime updatedOn;
@PrePersist
public void prePersist() {
createdOn = LocalDateTime.now();
}
@PreUpdate
public void preUpdate() {
updatedOn = LocalDateTime.now();
}
//Getters and setters omitted for brevity
}
然后将可嵌入的审计添加到实体,如下所示:
@Entity(name = "Tag")
@Table(name = "tag")
public class Tag {
@Id
private String name;
@Embedded
private Audit audit = new Audit();
//Getters and setters omitted for brevity
}
休眠特定的@CreationTimestamp和@UpdateTimestamp
@CreationTimestamp
@Column(name = "created_on")
private Date createdOn;
@Column(name = "updated_on")
@UpdateTimestamp
private Date updatedOn;
而已!
现在,与您的评论有关:
But what I get is that when I update one row, the timestamps for all of the rows updated, so all of the timestamps in the table are always the same. What am I doing wrong here?
时间戳只会针对要修改的实体进行更新,而不会针对所有行进行更新.仅修改一行时,更新所有行的时间戳没有任何意义.否则,为什么要在行本身上显示该列?
如果您想要最后的修改时间戳,只需运行如下查询:
SELECT MAX(updated_on)
FROM tags
标签:postgresql,jpa,hibernate,timestamp,java 来源: https://codeday.me/bug/20191108/2008459.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。