Обновление метки времени для каждой строки в Hibernate - PullRequest
0 голосов
/ 06 октября 2018

В моей базе данных 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

@PreUpdate
    private void onUpdate(){
        this.lastEditDate = new Date();
    }

@ UpdateTimestamp

@UpdateTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    private Date lastEditDate;

Но что я получаюв том, что когда я обновляю одну строку, метки времени для всех строк обновляются, поэтому все метки времени в таблице всегда одинаковы.Что я здесь не так делаю?

Ответы [ 2 ]

0 голосов
/ 10 октября 2018

Есть много способов достичь этой цели.

@ EntityListener

Как объяснено в этой статье , вы можете иметь @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());
    }
}

Вам необходимо будет реализовать интерфейс Audit:

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

Как я объяснил в этой статье , вы также можете использовать аннотации @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
}

и добавить встраиваемое Auditдля сущности, подобной этой:

@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
}

для Hibernate * @CreationTimestamp и @UpdateTimestamp

@CreationTimestamp
@Column(name = "created_on")
private Date createdOn;

@Column(name = "updated_on")
@UpdateTimestamp
private Date updatedOn;

Вот и все!

Теперь, связанные с вашим комментарием:

Но что я получаю, так это то, что при обновлении одной строки обновляются метки времени для всех строк, поэтому все метки времени в таблицеспособы одинаковые.Что я здесь не так делаю?

Отметка времени будет обновляться только для изменяемой сущности, а не для всех строк.Не имеет смысла обновлять временную метку всех строк, когда изменяется только одна строка.В противном случае, зачем вам этот столбец в самой строке?

Если вы хотите использовать метку времени последнего изменения, просто запустите такой запрос:

SELECT MAX(updated_on)
FROM tags
0 голосов
/ 06 октября 2018

Если вы используете данные весны, то вы делаете это с помощью функции аудита.Оформить заказ @EnableJpaAuditing или прочитать эту статью https://www.baeldung.com/database-auditing-jpa

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...