微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐