Подтвердить что ты не робот

Триггеры против JPA-события

Я делаю веб-приложение, используя Spring 3.1.0.RELEASE, JSF 2.x, JPA 2 с провайдером Hibernate, MySql 5.1.x. Приложение работает на Tomcat 7.X.

В моих сущностях у меня есть дата, как дата последнего обновления:

@Column(name = "last_update_date", insertable = false, updatable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date lastUpdateDate;

На данный момент у меня есть триггер, который обновляет:

CREATE TRIGGER upd_site BEFORE UPDATE ON site
FOR EACH ROW SET NEW.last_update_date = CURRENT_TIMESTAMP();

Он отлично работает, но я просто замечаю, что есть некоторые методы обратных вызовов в JPA http://www.objectdb.com/java/jpa/persistence/event

Что лучше между событиями JPA и триггерами MySql?

Спасибо.

4b9b3361

Ответ 1

Я использовал его в обоих режимах с помощью триггеров в базе данных и с слушателями JPA, я остановился на слушателях JPA, потому что:

  • единственный код, говорящий с базой данных в JPA-коде, поэтому мне не нужно беспокоиться о том, что поля временной метки не соответствуют дате. (Если это изменится в будущем, я могу добавить триггеры и изменить мои настроенные супер-кальки)

  • Слушатели JPA менее сложны в том смысле, что мне не нужно было создавать множество триггеров в моей базе данных, поэтому у меня было меньше вещей для поддержки. Поскольку я активно развиваю и меняю структуру db, я стараюсь не переходить и обновлять триггеры, поскольку я быстро перебираю развитие.

  • Я имею полный контроль над базой данных и сделал правило для db, что каждая таблица будет иметь целочисленный pkey и целочисленную версию, а таблицы с меткой времени будут иметь insert_ts и update_ts, это универсальные правила в моем дизайне db, поэтому жизнь проста. Я имею эти две отображаемые суперклассы, которые делают все мои enitites простыми для кодирования, поскольку я расширяюсь от них.

@MappedSuperclass
public abstract class PersistableObject {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="pkey")
    private Integer pkey;

    @Version
    @Column(name="version")
    private Integer version;

    public Integer getPkey() {
        return this.pkey;
    }

    public Integer getVersion() {
        return this.version;
    }

    @Override
    public String toString() {
        return "Presistable Object: pkey=" + this.pkey + " Object: " + this.getClass().getName();
    }
}

и

@MappedSuperclass
public class TimeStampedPersistableObject extends PersistableObject {

    @Column(name = "insert_ts")
    @Temporal(TemporalType.TIMESTAMP)
    private Date    insertTimestamp;

    @Column(name = "update_ts")
    @Temporal(TemporalType.TIMESTAMP)
    private Date    updateTimestamp;

    @SuppressWarnings("unused")
    @PrePersist
    private void onInsert() {
        this.insertTimestamp = new Date();
        this.updateTimestamp = this.insertTimestamp;
    }

    @SuppressWarnings("unused")
    @PreUpdate
    private void onUpdate() {
        this.updateTimestamp = new Date();
    }


    public Date getInsertTimestamp() {
        return this.insertTimestamp;
    }


    public Date getUpdateTimestamp() {
        return this.updateTimestamp;
    }
}

Ответ 2

Нет лучшего. Триггер базы данных обновляет последнюю дату обновления при каждом обновлении строки независимо от способа обновления строки (Hibernate, JDBC-запрос или обновление из инструмента администрирования базы данных). Обратный вызов JPA будет вызываться только при обновлении строки с использованием JPA. Вы можете захотеть того или другого.

Еще одно отличие заключается в том, что JPA не знает триггер, выполняемый базой данных. Поэтому, если вы обновите какое-то поле в своей сущности, а JPA сбросит это изменение, дата обновления будет изменена триггером, но объект JPA сохранит старое значение даты обновления в памяти. Поэтому, если эта дата обновления отображается в графическом интерфейсе после обновления, дата обновления будет неправильной. Вам нужно будет обновить объект, чтобы получить самую последнюю дату обновления.